/// Obtains a sorted list of functions that are undefined but ODR-used. void Sema::getUndefinedButUsed( SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined) { for (llvm::DenseMap<NamedDecl *, SourceLocation>::iterator I = UndefinedButUsed.begin(), E = UndefinedButUsed.end(); I != E; ++I) { NamedDecl *ND = I->first; // Ignore attributes that have become invalid. if (ND->isInvalidDecl()) continue; // __attribute__((weakref)) is basically a definition. if (ND->hasAttr<WeakRefAttr>()) continue; if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) { if (FD->isDefined()) continue; if (FD->hasExternalLinkage() && !FD->getMostRecentDecl()->isInlined()) continue; } else { if (cast<VarDecl>(ND)->hasDefinition() != VarDecl::DeclarationOnly) continue; if (ND->hasExternalLinkage()) continue; } Undefined.push_back(std::make_pair(ND, I->second)); } // Sort (in order of use site) so that we're not dependent on the iteration // order through an llvm::DenseMap. std::sort(Undefined.begin(), Undefined.end(), SortUndefinedButUsed(Context.getSourceManager())); }
/// checkUndefinedInternals - Check for undefined objects with internal linkage. static void checkUndefinedInternals(Sema &S) { if (S.UndefinedInternals.empty()) return; // Collect all the still-undefined entities with internal linkage. SmallVector<UndefinedInternal, 16> undefined; for (llvm::MapVector<NamedDecl*,SourceLocation>::iterator i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end(); i != e; ++i) { NamedDecl *decl = i->first; // Ignore attributes that have become invalid. if (decl->isInvalidDecl()) continue; // If we found out that the decl is external, don't warn. if (decl->getLinkage() == ExternalLinkage) continue; // __attribute__((weakref)) is basically a definition. if (decl->hasAttr<WeakRefAttr>()) continue; if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { if (fn->isPure() || fn->hasBody()) continue; } else { if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly) continue; } S.Diag(decl->getLocation(), diag::warn_undefined_internal) << isa<VarDecl>(decl) << decl; S.Diag(i->second, diag::note_used_here); } }
/// checkUndefinedInternals - Check for undefined objects with internal linkage. static void checkUndefinedInternals(Sema &S) { if (S.UndefinedInternals.empty()) return; // Collect all the still-undefined entities with internal linkage. SmallVector<UndefinedInternal, 16> undefined; for (llvm::DenseMap<NamedDecl*,SourceLocation>::iterator i = S.UndefinedInternals.begin(), e = S.UndefinedInternals.end(); i != e; ++i) { NamedDecl *decl = i->first; // Ignore attributes that have become invalid. if (decl->isInvalidDecl()) continue; // __attribute__((weakref)) is basically a definition. if (decl->hasAttr<WeakRefAttr>()) continue; if (FunctionDecl *fn = dyn_cast<FunctionDecl>(decl)) { if (fn->isPure() || fn->hasBody()) continue; } else { if (cast<VarDecl>(decl)->hasDefinition() != VarDecl::DeclarationOnly) continue; } // We build a FullSourceLoc so that we can sort with array_pod_sort. FullSourceLoc loc(i->second, S.Context.getSourceManager()); undefined.push_back(UndefinedInternal(decl, loc)); } if (undefined.empty()) return; // Sort (in order of use site) so that we're not (as) dependent on // the iteration order through an llvm::DenseMap. llvm::array_pod_sort(undefined.begin(), undefined.end()); for (SmallVectorImpl<UndefinedInternal>::iterator i = undefined.begin(), e = undefined.end(); i != e; ++i) { NamedDecl *decl = i->decl; S.Diag(decl->getLocation(), diag::warn_undefined_internal) << isa<VarDecl>(decl) << decl; S.Diag(i->useLoc, diag::note_used_here); } }
///\brief Checks for clashing names when trying to extract a declaration. /// ///\returns true if there is another declaration with the same name bool DeclExtractor::CheckForClashingNames( const llvm::SmallVector<NamedDecl*, 4>& Decls, DeclContext* DC, Scope* S) { for (size_t i = 0; i < Decls.size(); ++i) { NamedDecl* ND = Decls[i]; if (TagDecl* TD = dyn_cast<TagDecl>(ND)) { LookupResult Previous(*m_Sema, ND->getDeclName(), ND->getLocation(), Sema::LookupTagName, Sema::ForRedeclaration ); m_Sema->LookupName(Previous, S); // There is no function diagnosing the redeclaration of tags (eg. enums). // So either we have to do it by hand or we can call the top-most // function that does the check. Currently the top-most clang function // doing the checks creates an AST node, which we don't want. CheckTagDeclaration(TD, Previous); } else if (VarDecl* VD = dyn_cast<VarDecl>(ND)) { LookupResult Previous(*m_Sema, ND->getDeclName(), ND->getLocation(), Sema::LookupOrdinaryName, Sema::ForRedeclaration ); m_Sema->LookupName(Previous, S); m_Sema->CheckVariableDeclaration(VD, Previous); } if (ND->isInvalidDecl()) return true; } return false; }
Action::OwningExprResult Sema::BuildMemberReferenceExpr(Expr *BaseExpr, const Type *BaseExprType, SourceLocation OpLoc, LookupResult &R) { const Type* BaseType = BaseExprType; if (const PointerType *P = dyn_cast<PointerType>(BaseType)) BaseType = P->getPointeeType(); //R.setBaseObjectType(BaseType); //const DeclarationNameInfo &MemberNameInfo = R.getLookupNameInfo(); //DeclarationName MemberName = MemberNameInfo.getName(); //SourceLocation MemberLoc = MemberNameInfo.getLoc(); IdentifierInfo *II = R.getLookupName(); if (R.isAmbiguous()) return ExprError(); if (R.empty()) { // FIXME: make sure this prints the '*' for pointer-to-struct types (?) //DeclContext *DC = BaseType->getAs<StructType>()->getDecl(); // FIXME: clang prints DC instead of BaseExprType here. Don't do that, // else we don't print struct names right. However, make sure ParenTypes // get desugared once they exist. Diag(R.getNameLoc(), diag::no_field) << II << BaseExprType; //Diag(R.getNameLoc(), diag::err_no_member) //<< MemberName << DC //<< (BaseExpr ? BaseExpr->getSourceRange() : SourceRange()); return ExprError(); } assert(R.isSingleResult()); NamedDecl *MemberDecl = R.getFoundDecl(); #if 0 DeclAccessPair FoundDecl = R.begin().getPair(); // If the decl being referenced had an error, return an error for this // sub-expr without emitting another error, in order to avoid cascading // error cases. if (MemberDecl->isInvalidDecl()) return ExprError(); bool ShouldCheckUse = true; if (CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(MemberDecl)) { // Don't diagnose the use of a virtual member function unless it's // explicitly qualified. if (MD->isVirtual()) ShouldCheckUse = false; } // Check the use of this member. if (ShouldCheckUse && DiagnoseUseOfDecl(MemberDecl, MemberLoc)) { Owned(BaseExpr); return ExprError(); } #endif if (FieldDecl *FD = dyn_cast<FieldDecl>(MemberDecl)) { //return BuildFieldReferenceExpr(*this, BaseExpr, IsArrow, //FD, FoundDecl, MemberNameInfo); return Owned(BuildMemberExpr(*this, Context, BaseExpr, FD, R.getNameLoc(), FD->getType())); } #if 0 if (IndirectFieldDecl *FD = dyn_cast<IndirectFieldDecl>(MemberDecl)) // We may have found a field within an anonymous union or struct // (C++ [class.union]). return BuildAnonymousStructUnionMemberReference(MemberLoc, FD, BaseExpr, OpLoc); if (VarDecl *Var = dyn_cast<VarDecl>(MemberDecl)) { return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, Var, FoundDecl, MemberNameInfo, Var->getType().getNonReferenceType(), VK_LValue, OK_Ordinary)); } if (CXXMethodDecl *MemberFn = dyn_cast<CXXMethodDecl>(MemberDecl)) { ExprValueKind valueKind; QualType type; if (MemberFn->isInstance()) { valueKind = VK_RValue; type = Context.BoundMemberTy; } else { valueKind = VK_LValue; type = MemberFn->getType(); } return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, MemberFn, FoundDecl, MemberNameInfo, type, valueKind, OK_Ordinary)); } assert(!isa<FunctionDecl>(MemberDecl) && "member function not C++ method?"); if (EnumConstantDecl *Enum = dyn_cast<EnumConstantDecl>(MemberDecl)) { return Owned(BuildMemberExpr(*this, Context, BaseExpr, IsArrow, Enum, FoundDecl, MemberNameInfo, Enum->getType(), VK_RValue, OK_Ordinary)); } Owned(BaseExpr); // We found something that we didn't expect. Complain. if (isa<TypeDecl>(MemberDecl)) Diag(MemberLoc, diag::err_typecheck_member_reference_type) << MemberName << BaseType << int(IsArrow); else Diag(MemberLoc, diag::err_typecheck_member_reference_unknown) << MemberName << BaseType << int(IsArrow); Diag(MemberDecl->getLocation(), diag::note_member_declared_here) << MemberName; R.suppressDiagnostics(); #endif return ExprError(); }