diff options
author | Alp Toker <alp@nuanti.com> | 2014-01-22 07:29:52 +0000 |
---|---|---|
committer | Alp Toker <alp@nuanti.com> | 2014-01-22 07:29:52 +0000 |
commit | a2794f9f363361f87a3538b90b78ff13381d5ce1 (patch) | |
tree | 5cc9768890e4532cd0625ba7ffbe54d2c35d5b35 /clang/lib/Sema | |
parent | 217c640ee85825f734ffce2ff6305e3e29003262 (diff) | |
download | bcm5719-llvm-a2794f9f363361f87a3538b90b78ff13381d5ce1.tar.gz bcm5719-llvm-a2794f9f363361f87a3538b90b78ff13381d5ce1.zip |
Introduce and use Decl::getAsFunction() to simplify templated function checks
Lift the getFunctionDecl() utility out of the parser into a general
Decl::getAsFunction() and use it to simplify other parts of the implementation.
Reduce isFunctionOrFunctionTemplate() to a simple type check that works the
same was as the other is* functions and move unwrapping of shadowed decls to
callers so it doesn't get run twice.
Shuffle around canSkipFunctionBody() to reduce virtual dispatch on ASTConsumer.
There's no need to query when we already know the body can't be skipped.
llvm-svn: 199794
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaAccess.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCodeComplete.cpp | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 50 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLookup.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOverload.cpp | 15 |
6 files changed, 36 insertions, 101 deletions
diff --git a/clang/lib/Sema/SemaAccess.cpp b/clang/lib/Sema/SemaAccess.cpp index 7722ba9fe95..c00ad81b097 100644 --- a/clang/lib/Sema/SemaAccess.cpp +++ b/clang/lib/Sema/SemaAccess.cpp @@ -1081,15 +1081,15 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC, (isa<FunctionTemplateDecl>(D) && isa<CXXConstructorDecl>( cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) { - S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor) - << isa<CXXDestructorDecl>(D); - return true; + return S.Diag(D->getLocation(), + diag::note_access_protected_restricted_ctordtor) + << isa<CXXDestructorDecl>(D->getAsFunction()); } // Otherwise, use the generic diagnostic. - S.Diag(D->getLocation(), diag::note_access_protected_restricted_object) - << S.Context.getTypeDeclType(ECRecord); - return true; + return S.Diag(D->getLocation(), + diag::note_access_protected_restricted_object) + << S.Context.getTypeDeclType(ECRecord); } return false; @@ -1748,10 +1748,7 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc, /// Checks access to the target of a friend declaration. Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) { - assert(isa<CXXMethodDecl>(target) || - (isa<FunctionTemplateDecl>(target) && - isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(target) - ->getTemplatedDecl()))); + assert(isa<CXXMethodDecl>(target->getAsFunction())); // Friendship lookup is a redeclaration lookup, so there's never an // inheritance path modifying access. @@ -1760,10 +1757,7 @@ Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) { if (!getLangOpts().AccessControl || access == AS_public) return AR_accessible; - CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target); - if (!method) - method = cast<CXXMethodDecl>( - cast<FunctionTemplateDecl>(target)->getTemplatedDecl()); + CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target->getAsFunction()); assert(method->getQualifier()); AccessTarget entity(Context, AccessTarget::Member, diff --git a/clang/lib/Sema/SemaCodeComplete.cpp b/clang/lib/Sema/SemaCodeComplete.cpp index 73a758db643..33909c73077 100644 --- a/clang/lib/Sema/SemaCodeComplete.cpp +++ b/clang/lib/Sema/SemaCodeComplete.cpp @@ -660,13 +660,10 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { return C.getObjCInterfaceType(Iface); QualType T; - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) + if (const FunctionDecl *Function = ND->getAsFunction()) T = Function->getCallResultType(); else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) T = Method->getSendResultType(); - else if (const FunctionTemplateDecl *FunTmpl = - dyn_cast<FunctionTemplateDecl>(ND)) - T = FunTmpl->getTemplatedDecl()->getCallResultType(); else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND)) @@ -2066,14 +2063,11 @@ static void AddResultTypeChunk(ASTContext &Context, return; // Determine the type of the declaration (if it has a type). - QualType T; - if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) + QualType T; + if (const FunctionDecl *Function = ND->getAsFunction()) T = Function->getResultType(); else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) T = Method->getResultType(); - else if (const FunctionTemplateDecl *FunTmpl = - dyn_cast<FunctionTemplateDecl>(ND)) - T = FunTmpl->getTemplatedDecl()->getResultType(); else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND)) T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext())); else if (isa<UnresolvedUsingValueDecl>(ND)) { diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9dac4d53024..949526b3edf 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -845,7 +845,8 @@ Corrected: // seems likely a type is wanted instead of the non-type that was found. bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star); if ((NextToken.is(tok::identifier) || - (NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) && + (NextIsOp && + FirstDecl->getUnderlyingDecl()->isFunctionOrFunctionTemplate())) && isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) { TypeDecl *Type = Result.getAsSingle<TypeDecl>(); DiagnoseUseOfDecl(Type, NameLoc); @@ -962,12 +963,9 @@ void Sema::ExitDeclaratorContext(Scope *S) { void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) { - FunctionDecl *FD = dyn_cast<FunctionDecl>(D); - if (FunctionTemplateDecl *TFD = dyn_cast_or_null<FunctionTemplateDecl>(D)) { - // We assume that the caller has already called - // ActOnReenterTemplateScope - FD = TFD->getTemplatedDecl(); - } + // We assume that the caller has already called + // ActOnReenterTemplateScope so getTemplatedDecl() works. + FunctionDecl *FD = D->getAsFunction(); if (!FD) return; @@ -2270,12 +2268,7 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) { bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S, bool MergeTypeWithOld) { // Verify the old decl was also a function. - FunctionDecl *Old = 0; - if (FunctionTemplateDecl *OldFunctionTemplate - = dyn_cast<FunctionTemplateDecl>(OldD)) - Old = OldFunctionTemplate->getTemplatedDecl(); - else - Old = dyn_cast<FunctionDecl>(OldD); + FunctionDecl *Old = OldD->getAsFunction(); if (!Old) { if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) { if (New->getFriendObjectKind()) { @@ -7474,10 +7467,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() && !MD->isStatic() && !isa<CXXConstructorDecl>(MD) && (MD->getTypeQualifiers() & Qualifiers::Const) == 0) { - CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl); - if (FunctionTemplateDecl *OldTD = - dyn_cast_or_null<FunctionTemplateDecl>(OldDecl)) - OldMD = dyn_cast<CXXMethodDecl>(OldTD->getTemplatedDecl()); + CXXMethodDecl *OldMD = 0; + if (OldDecl) + OldMD = dyn_cast<CXXMethodDecl>(OldDecl->getAsFunction()); if (!OldMD || !OldMD->isStatic()) { const FunctionProtoType *FPT = MD->getType()->castAs<FunctionProtoType>(); @@ -9699,24 +9691,15 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) { } bool Sema::canSkipFunctionBody(Decl *D) { - if (!Consumer.shouldSkipFunctionBody(D)) - return false; - - if (isa<ObjCMethodDecl>(D)) - return true; - - FunctionDecl *FD = 0; - if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) - FD = FTD->getTemplatedDecl(); - else - FD = cast<FunctionDecl>(D); - // We cannot skip the body of a function (or function template) which is // constexpr, since we may need to evaluate its body in order to parse the // rest of the file. // We cannot skip the body of a function with an undeduced return type, // because any callers of that function need to know the type. - return !FD->isConstexpr() && !FD->getResultType()->isUndeducedType(); + if (const FunctionDecl *FD = D->getAsFunction()) + if (FD->isConstexpr() || FD->getResultType()->isUndeducedType()) + return false; + return Consumer.shouldSkipFunctionBody(D); } Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) { @@ -9733,12 +9716,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) { Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, bool IsInstantiation) { - FunctionDecl *FD = 0; - FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl); - if (FunTmpl) - FD = FunTmpl->getTemplatedDecl(); - else - FD = dyn_cast_or_null<FunctionDecl>(dcl); + FunctionDecl *FD = dcl ? dcl->getAsFunction() : 0; sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy(); sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0; diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 76b9d669d42..3fe6337d502 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7242,13 +7242,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig, if (FoundEquivalentDecl) return false; - if (Target->isFunctionOrFunctionTemplate()) { - FunctionDecl *FD; - if (isa<FunctionTemplateDecl>(Target)) - FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl(); - else - FD = cast<FunctionDecl>(Target); - + if (FunctionDecl *FD = Target->getAsFunction()) { NamedDecl *OldDecl = 0; switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) { case Ovl_Overload: diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp index 7b6536973ae..0f5a78b10a1 100644 --- a/clang/lib/Sema/SemaLookup.cpp +++ b/clang/lib/Sema/SemaLookup.cpp @@ -2320,11 +2320,7 @@ void Sema::FindAssociatedClassesAndNamespaces( for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end(); I != E; ++I) { // Look through any using declarations to find the underlying function. - NamedDecl *Fn = (*I)->getUnderlyingDecl(); - - FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn); - if (!FDecl) - FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl(); + FunctionDecl *FDecl = (*I)->getUnderlyingDecl()->getAsFunction(); // Add the classes and namespaces associated with the parameter // types and return type of this function. @@ -2814,14 +2810,8 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R, // operator template, but not both. if (FoundRaw && FoundTemplate) { Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName(); - for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) { - Decl *D = *I; - if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D)) - D = USD->getTargetDecl(); - if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D)) - D = FunTmpl->getTemplatedDecl(); - NoteOverloadCandidate(cast<FunctionDecl>(D)); - } + for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) + NoteOverloadCandidate((*I)->getUnderlyingDecl()->getAsFunction()); return LOLR_Error; } @@ -2853,14 +2843,8 @@ void ADLResult::insert(NamedDecl *New) { } // Otherwise, decide which is a more recent redeclaration. - FunctionDecl *OldFD, *NewFD; - if (isa<FunctionTemplateDecl>(New)) { - OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl(); - NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl(); - } else { - OldFD = cast<FunctionDecl>(Old); - NewFD = cast<FunctionDecl>(New); - } + FunctionDecl *OldFD = Old->getAsFunction(); + FunctionDecl *NewFD = New->getAsFunction(); FunctionDecl *Cursor = NewFD; while (true) { @@ -3065,8 +3049,8 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) { // Functions and function templates in the same scope overload // rather than hide. FIXME: Look for hiding based on function // signatures! - if ((*I)->isFunctionOrFunctionTemplate() && - ND->isFunctionOrFunctionTemplate() && + if ((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate() && + ND->getUnderlyingDecl()->isFunctionOrFunctionTemplate() && SM == ShadowMaps.rbegin()) continue; diff --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp index 7d35bcabfe2..af47cb4bba0 100644 --- a/clang/lib/Sema/SemaOverload.cpp +++ b/clang/lib/Sema/SemaOverload.cpp @@ -930,24 +930,15 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old, (OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() && !New->getFriendObjectKind(); - if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) { - if (!IsOverload(New, OldT->getTemplatedDecl(), UseMemberUsingDeclRules)) { - if (UseMemberUsingDeclRules && OldIsUsingDecl) { - HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); - continue; - } - - Match = *I; - return Ovl_Match; - } - } else if (FunctionDecl *OldF = dyn_cast<FunctionDecl>(OldD)) { + if (FunctionDecl *OldF = OldD->getAsFunction()) { if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) { if (UseMemberUsingDeclRules && OldIsUsingDecl) { HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I)); continue; } - if (!shouldLinkPossiblyHiddenDecl(*I, New)) + if (!isa<FunctionTemplateDecl>(OldD) && + !shouldLinkPossiblyHiddenDecl(*I, New)) continue; Match = *I; |