forked from OSchip/llvm-project
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
This commit is contained in:
parent
217c640ee8
commit
a2794f9f36
|
@ -110,7 +110,7 @@ class NamedDecl : public Decl {
|
||||||
DeclarationName Name;
|
DeclarationName Name;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NamedDecl *getUnderlyingDeclImpl();
|
NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
|
NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
|
||||||
|
|
|
@ -837,7 +837,19 @@ public:
|
||||||
bool isTemplateDecl() const;
|
bool isTemplateDecl() const;
|
||||||
|
|
||||||
/// \brief Whether this declaration is a function or function template.
|
/// \brief Whether this declaration is a function or function template.
|
||||||
bool isFunctionOrFunctionTemplate() const;
|
bool isFunctionOrFunctionTemplate() const {
|
||||||
|
return (DeclKind >= Decl::firstFunction &&
|
||||||
|
DeclKind <= Decl::lastFunction) ||
|
||||||
|
DeclKind == FunctionTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Returns the function itself, or the templated function if this is a
|
||||||
|
/// function template.
|
||||||
|
FunctionDecl *getAsFunction() LLVM_READONLY;
|
||||||
|
|
||||||
|
const FunctionDecl *getAsFunction() const {
|
||||||
|
return const_cast<Decl *>(this)->getAsFunction();
|
||||||
|
}
|
||||||
|
|
||||||
/// \brief Changes the namespace of this declaration to reflect that it's
|
/// \brief Changes the namespace of this declaration to reflect that it's
|
||||||
/// a function-local extern declaration.
|
/// a function-local extern declaration.
|
||||||
|
|
|
@ -561,16 +561,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
|
||||||
if (PrevVar->getStorageClass() == SC_Static)
|
if (PrevVar->getStorageClass() == SC_Static)
|
||||||
return LinkageInfo::internal();
|
return LinkageInfo::internal();
|
||||||
}
|
}
|
||||||
} else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
|
} else if (const FunctionDecl *Function = D->getAsFunction()) {
|
||||||
// C++ [temp]p4:
|
// C++ [temp]p4:
|
||||||
// A non-member function template can have internal linkage; any
|
// A non-member function template can have internal linkage; any
|
||||||
// other template name shall have external linkage.
|
// other template name shall have external linkage.
|
||||||
const FunctionDecl *Function = 0;
|
|
||||||
if (const FunctionTemplateDecl *FunTmpl
|
|
||||||
= dyn_cast<FunctionTemplateDecl>(D))
|
|
||||||
Function = FunTmpl->getTemplatedDecl();
|
|
||||||
else
|
|
||||||
Function = cast<FunctionDecl>(D);
|
|
||||||
|
|
||||||
// Explicitly declared static.
|
// Explicitly declared static.
|
||||||
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
|
if (Function->getCanonicalDecl()->getStorageClass() == SC_Static)
|
||||||
|
@ -1456,11 +1450,9 @@ bool NamedDecl::isCXXInstanceMember() const {
|
||||||
|
|
||||||
if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
|
if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D))
|
||||||
return true;
|
return true;
|
||||||
if (isa<CXXMethodDecl>(D))
|
if (const CXXMethodDecl *MD =
|
||||||
return cast<CXXMethodDecl>(D)->isInstance();
|
dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()))
|
||||||
if (isa<FunctionTemplateDecl>(D))
|
return MD->isInstance();
|
||||||
return cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D)
|
|
||||||
->getTemplatedDecl())->isInstance();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -159,11 +159,12 @@ bool Decl::isParameterPack() const {
|
||||||
return isTemplateParameterPack();
|
return isTemplateParameterPack();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decl::isFunctionOrFunctionTemplate() const {
|
FunctionDecl *Decl::getAsFunction() {
|
||||||
if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this))
|
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(this))
|
||||||
return UD->getTargetDecl()->isFunctionOrFunctionTemplate();
|
return FD;
|
||||||
|
if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(this))
|
||||||
return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this);
|
return FTD->getTemplatedDecl();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Decl::isTemplateDecl() const {
|
bool Decl::isTemplateDecl() const {
|
||||||
|
|
|
@ -1030,13 +1030,9 @@ CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
|
static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
|
||||||
QualType T;
|
QualType T =
|
||||||
if (isa<UsingShadowDecl>(Conv))
|
cast<CXXConversionDecl>(Conv->getUnderlyingDecl()->getAsFunction())
|
||||||
Conv = cast<UsingShadowDecl>(Conv)->getTargetDecl();
|
->getConversionType();
|
||||||
if (FunctionTemplateDecl *ConvTemp = dyn_cast<FunctionTemplateDecl>(Conv))
|
|
||||||
T = ConvTemp->getTemplatedDecl()->getResultType();
|
|
||||||
else
|
|
||||||
T = cast<CXXConversionDecl>(Conv)->getConversionType();
|
|
||||||
return Context.getCanonicalType(T);
|
return Context.getCanonicalType(T);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1291,16 +1291,11 @@ static bool hasOnlyNonStaticMemberFunctions(UnresolvedSetIterator begin,
|
||||||
NamedDecl *decl = *begin;
|
NamedDecl *decl = *begin;
|
||||||
if (isa<UnresolvedUsingValueDecl>(decl))
|
if (isa<UnresolvedUsingValueDecl>(decl))
|
||||||
return false;
|
return false;
|
||||||
if (isa<UsingShadowDecl>(decl))
|
|
||||||
decl = cast<UsingShadowDecl>(decl)->getUnderlyingDecl();
|
|
||||||
|
|
||||||
// Unresolved member expressions should only contain methods and
|
// Unresolved member expressions should only contain methods and
|
||||||
// method templates.
|
// method templates.
|
||||||
assert(isa<CXXMethodDecl>(decl) || isa<FunctionTemplateDecl>(decl));
|
if (cast<CXXMethodDecl>(decl->getUnderlyingDecl()->getAsFunction())
|
||||||
|
->isStatic())
|
||||||
if (isa<FunctionTemplateDecl>(decl))
|
|
||||||
decl = cast<FunctionTemplateDecl>(decl)->getTemplatedDecl();
|
|
||||||
if (cast<CXXMethodDecl>(decl)->isStatic())
|
|
||||||
return false;
|
return false;
|
||||||
} while (++begin != end);
|
} while (++begin != end);
|
||||||
|
|
||||||
|
|
|
@ -19,13 +19,6 @@
|
||||||
#include "clang/Sema/Scope.h"
|
#include "clang/Sema/Scope.h"
|
||||||
using namespace clang;
|
using namespace clang;
|
||||||
|
|
||||||
/// Get the FunctionDecl for a function or function template decl.
|
|
||||||
static FunctionDecl *getFunctionDecl(Decl *D) {
|
|
||||||
if (FunctionDecl *fn = dyn_cast<FunctionDecl>(D))
|
|
||||||
return fn;
|
|
||||||
return cast<FunctionTemplateDecl>(D)->getTemplatedDecl();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
|
/// ParseCXXInlineMethodDef - We parsed and verified that the specified
|
||||||
/// Declarator is a well formed C++ inline method definition. Now lex its body
|
/// Declarator is a well formed C++ inline method definition. Now lex its body
|
||||||
/// and store its tokens for parsing after the C++ class is complete.
|
/// and store its tokens for parsing after the C++ class is complete.
|
||||||
|
@ -110,8 +103,8 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
|
||||||
if (getLangOpts().DelayedTemplateParsing &&
|
if (getLangOpts().DelayedTemplateParsing &&
|
||||||
DefinitionKind == FDK_Definition &&
|
DefinitionKind == FDK_Definition &&
|
||||||
!D.getDeclSpec().isConstexprSpecified() &&
|
!D.getDeclSpec().isConstexprSpecified() &&
|
||||||
!(FnD && getFunctionDecl(FnD) &&
|
!(FnD && FnD->getAsFunction() &&
|
||||||
getFunctionDecl(FnD)->getResultType()->getContainedAutoType()) &&
|
FnD->getAsFunction()->getResultType()->getContainedAutoType()) &&
|
||||||
((Actions.CurContext->isDependentContext() ||
|
((Actions.CurContext->isDependentContext() ||
|
||||||
(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
|
(TemplateInfo.Kind != ParsedTemplateInfo::NonTemplate &&
|
||||||
TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) &&
|
TemplateInfo.Kind != ParsedTemplateInfo::ExplicitSpecialization)) &&
|
||||||
|
@ -121,7 +114,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
|
||||||
LexTemplateFunctionForLateParsing(Toks);
|
LexTemplateFunctionForLateParsing(Toks);
|
||||||
|
|
||||||
if (FnD) {
|
if (FnD) {
|
||||||
FunctionDecl *FD = getFunctionDecl(FnD);
|
FunctionDecl *FD = FnD->getAsFunction();
|
||||||
Actions.CheckForFunctionRedefinition(FD);
|
Actions.CheckForFunctionRedefinition(FD);
|
||||||
Actions.MarkAsLateParsedTemplate(FD, FnD, Toks);
|
Actions.MarkAsLateParsedTemplate(FD, FnD, Toks);
|
||||||
}
|
}
|
||||||
|
@ -173,7 +166,7 @@ NamedDecl *Parser::ParseCXXInlineMethodDef(AccessSpecifier AS,
|
||||||
// If you remove this, you can remove the code that clears the flag
|
// If you remove this, you can remove the code that clears the flag
|
||||||
// after parsing the member.
|
// after parsing the member.
|
||||||
if (D.getDeclSpec().isFriendSpecified()) {
|
if (D.getDeclSpec().isFriendSpecified()) {
|
||||||
FunctionDecl *FD = getFunctionDecl(FnD);
|
FunctionDecl *FD = FnD->getAsFunction();
|
||||||
Actions.CheckForFunctionRedefinition(FD);
|
Actions.CheckForFunctionRedefinition(FD);
|
||||||
FD->setLateTemplateParsed(true);
|
FD->setLateTemplateParsed(true);
|
||||||
}
|
}
|
||||||
|
@ -456,7 +449,8 @@ void Parser::ParseLexedMethodDef(LexedMethod &LM) {
|
||||||
ParseFunctionStatementBody(LM.D, FnScope);
|
ParseFunctionStatementBody(LM.D, FnScope);
|
||||||
|
|
||||||
// Clear the late-template-parsed bit if we set it before.
|
// Clear the late-template-parsed bit if we set it before.
|
||||||
if (LM.D) getFunctionDecl(LM.D)->setLateTemplateParsed(false);
|
if (LM.D)
|
||||||
|
LM.D->getAsFunction()->setLateTemplateParsed(false);
|
||||||
|
|
||||||
if (Tok.getLocation() != origLoc) {
|
if (Tok.getLocation() != origLoc) {
|
||||||
// Due to parsing error, we either went over the cached tokens or
|
// Due to parsing error, we either went over the cached tokens or
|
||||||
|
|
|
@ -1227,9 +1227,7 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Get the FunctionDecl.
|
// Get the FunctionDecl.
|
||||||
FunctionTemplateDecl *FunTmplD = dyn_cast<FunctionTemplateDecl>(LPT.D);
|
FunctionDecl *FunD = LPT.D->getAsFunction();
|
||||||
FunctionDecl *FunD =
|
|
||||||
FunTmplD ? FunTmplD->getTemplatedDecl() : cast<FunctionDecl>(LPT.D);
|
|
||||||
// Track template parameter depth.
|
// Track template parameter depth.
|
||||||
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
|
TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
|
||||||
|
|
||||||
|
@ -1312,8 +1310,10 @@ void Parser::ParseLateTemplatedFuncDef(LateParsedTemplate &LPT) {
|
||||||
Actions.ActOnDefaultCtorInitializers(LPT.D);
|
Actions.ActOnDefaultCtorInitializers(LPT.D);
|
||||||
|
|
||||||
if (Tok.is(tok::l_brace)) {
|
if (Tok.is(tok::l_brace)) {
|
||||||
assert((!FunTmplD || FunTmplD->getTemplateParameters()->getDepth() <
|
assert((!isa<FunctionTemplateDecl>(LPT.D) ||
|
||||||
TemplateParameterDepth) &&
|
cast<FunctionTemplateDecl>(LPT.D)
|
||||||
|
->getTemplateParameters()
|
||||||
|
->getDepth() < TemplateParameterDepth) &&
|
||||||
"TemplateParameterDepth should be greater than the depth of "
|
"TemplateParameterDepth should be greater than the depth of "
|
||||||
"current template being instantiated!");
|
"current template being instantiated!");
|
||||||
ParseFunctionStatementBody(LPT.D, FnScope);
|
ParseFunctionStatementBody(LPT.D, FnScope);
|
||||||
|
|
|
@ -1085,12 +1085,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
|
||||||
LexTemplateFunctionForLateParsing(Toks);
|
LexTemplateFunctionForLateParsing(Toks);
|
||||||
|
|
||||||
if (DP) {
|
if (DP) {
|
||||||
FunctionDecl *FnD = 0;
|
FunctionDecl *FnD = DP->getAsFunction();
|
||||||
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(DP))
|
|
||||||
FnD = FunTmpl->getTemplatedDecl();
|
|
||||||
else
|
|
||||||
FnD = cast<FunctionDecl>(DP);
|
|
||||||
|
|
||||||
Actions.CheckForFunctionRedefinition(FnD);
|
Actions.CheckForFunctionRedefinition(FnD);
|
||||||
Actions.MarkAsLateParsedTemplate(FnD, DP, Toks);
|
Actions.MarkAsLateParsedTemplate(FnD, DP, Toks);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1081,15 +1081,15 @@ static bool TryDiagnoseProtectedAccess(Sema &S, const EffectiveContext &EC,
|
||||||
(isa<FunctionTemplateDecl>(D) &&
|
(isa<FunctionTemplateDecl>(D) &&
|
||||||
isa<CXXConstructorDecl>(
|
isa<CXXConstructorDecl>(
|
||||||
cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
|
cast<FunctionTemplateDecl>(D)->getTemplatedDecl()))) {
|
||||||
S.Diag(D->getLocation(), diag::note_access_protected_restricted_ctordtor)
|
return S.Diag(D->getLocation(),
|
||||||
<< isa<CXXDestructorDecl>(D);
|
diag::note_access_protected_restricted_ctordtor)
|
||||||
return true;
|
<< isa<CXXDestructorDecl>(D->getAsFunction());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, use the generic diagnostic.
|
// Otherwise, use the generic diagnostic.
|
||||||
S.Diag(D->getLocation(), diag::note_access_protected_restricted_object)
|
return S.Diag(D->getLocation(),
|
||||||
|
diag::note_access_protected_restricted_object)
|
||||||
<< S.Context.getTypeDeclType(ECRecord);
|
<< S.Context.getTypeDeclType(ECRecord);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1748,10 +1748,7 @@ Sema::AccessResult Sema::CheckMemberOperatorAccess(SourceLocation OpLoc,
|
||||||
|
|
||||||
/// Checks access to the target of a friend declaration.
|
/// Checks access to the target of a friend declaration.
|
||||||
Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
|
Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
|
||||||
assert(isa<CXXMethodDecl>(target) ||
|
assert(isa<CXXMethodDecl>(target->getAsFunction()));
|
||||||
(isa<FunctionTemplateDecl>(target) &&
|
|
||||||
isa<CXXMethodDecl>(cast<FunctionTemplateDecl>(target)
|
|
||||||
->getTemplatedDecl())));
|
|
||||||
|
|
||||||
// Friendship lookup is a redeclaration lookup, so there's never an
|
// Friendship lookup is a redeclaration lookup, so there's never an
|
||||||
// inheritance path modifying access.
|
// inheritance path modifying access.
|
||||||
|
@ -1760,10 +1757,7 @@ Sema::AccessResult Sema::CheckFriendAccess(NamedDecl *target) {
|
||||||
if (!getLangOpts().AccessControl || access == AS_public)
|
if (!getLangOpts().AccessControl || access == AS_public)
|
||||||
return AR_accessible;
|
return AR_accessible;
|
||||||
|
|
||||||
CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target);
|
CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(target->getAsFunction());
|
||||||
if (!method)
|
|
||||||
method = cast<CXXMethodDecl>(
|
|
||||||
cast<FunctionTemplateDecl>(target)->getTemplatedDecl());
|
|
||||||
assert(method->getQualifier());
|
assert(method->getQualifier());
|
||||||
|
|
||||||
AccessTarget entity(Context, AccessTarget::Member,
|
AccessTarget entity(Context, AccessTarget::Member,
|
||||||
|
|
|
@ -660,13 +660,10 @@ QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
|
||||||
return C.getObjCInterfaceType(Iface);
|
return C.getObjCInterfaceType(Iface);
|
||||||
|
|
||||||
QualType T;
|
QualType T;
|
||||||
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
|
if (const FunctionDecl *Function = ND->getAsFunction())
|
||||||
T = Function->getCallResultType();
|
T = Function->getCallResultType();
|
||||||
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
|
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
|
||||||
T = Method->getSendResultType();
|
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))
|
else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
|
||||||
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
|
T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
|
||||||
else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
|
else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
|
||||||
|
@ -2067,13 +2064,10 @@ static void AddResultTypeChunk(ASTContext &Context,
|
||||||
|
|
||||||
// Determine the type of the declaration (if it has a type).
|
// Determine the type of the declaration (if it has a type).
|
||||||
QualType T;
|
QualType T;
|
||||||
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
|
if (const FunctionDecl *Function = ND->getAsFunction())
|
||||||
T = Function->getResultType();
|
T = Function->getResultType();
|
||||||
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
|
else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
|
||||||
T = Method->getResultType();
|
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))
|
else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
|
||||||
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
|
T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
|
||||||
else if (isa<UnresolvedUsingValueDecl>(ND)) {
|
else if (isa<UnresolvedUsingValueDecl>(ND)) {
|
||||||
|
|
|
@ -845,7 +845,8 @@ Corrected:
|
||||||
// seems likely a type is wanted instead of the non-type that was found.
|
// seems likely a type is wanted instead of the non-type that was found.
|
||||||
bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
|
bool NextIsOp = NextToken.is(tok::amp) || NextToken.is(tok::star);
|
||||||
if ((NextToken.is(tok::identifier) ||
|
if ((NextToken.is(tok::identifier) ||
|
||||||
(NextIsOp && FirstDecl->isFunctionOrFunctionTemplate())) &&
|
(NextIsOp &&
|
||||||
|
FirstDecl->getUnderlyingDecl()->isFunctionOrFunctionTemplate())) &&
|
||||||
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
|
isTagTypeWithMissingTag(*this, Result, S, SS, Name, NameLoc)) {
|
||||||
TypeDecl *Type = Result.getAsSingle<TypeDecl>();
|
TypeDecl *Type = Result.getAsSingle<TypeDecl>();
|
||||||
DiagnoseUseOfDecl(Type, NameLoc);
|
DiagnoseUseOfDecl(Type, NameLoc);
|
||||||
|
@ -962,12 +963,9 @@ void Sema::ExitDeclaratorContext(Scope *S) {
|
||||||
|
|
||||||
|
|
||||||
void Sema::ActOnReenterFunctionContext(Scope* S, Decl *D) {
|
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
|
// We assume that the caller has already called
|
||||||
// ActOnReenterTemplateScope
|
// ActOnReenterTemplateScope so getTemplatedDecl() works.
|
||||||
FD = TFD->getTemplatedDecl();
|
FunctionDecl *FD = D->getAsFunction();
|
||||||
}
|
|
||||||
if (!FD)
|
if (!FD)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2270,12 +2268,7 @@ static bool haveIncompatibleLanguageLinkages(const T *Old, const T *New) {
|
||||||
bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
|
bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD, Scope *S,
|
||||||
bool MergeTypeWithOld) {
|
bool MergeTypeWithOld) {
|
||||||
// Verify the old decl was also a function.
|
// Verify the old decl was also a function.
|
||||||
FunctionDecl *Old = 0;
|
FunctionDecl *Old = OldD->getAsFunction();
|
||||||
if (FunctionTemplateDecl *OldFunctionTemplate
|
|
||||||
= dyn_cast<FunctionTemplateDecl>(OldD))
|
|
||||||
Old = OldFunctionTemplate->getTemplatedDecl();
|
|
||||||
else
|
|
||||||
Old = dyn_cast<FunctionDecl>(OldD);
|
|
||||||
if (!Old) {
|
if (!Old) {
|
||||||
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
|
if (UsingShadowDecl *Shadow = dyn_cast<UsingShadowDecl>(OldD)) {
|
||||||
if (New->getFriendObjectKind()) {
|
if (New->getFriendObjectKind()) {
|
||||||
|
@ -7474,10 +7467,9 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||||
if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() &&
|
if (!getLangOpts().CPlusPlus1y && MD && MD->isConstexpr() &&
|
||||||
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
|
!MD->isStatic() && !isa<CXXConstructorDecl>(MD) &&
|
||||||
(MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
|
(MD->getTypeQualifiers() & Qualifiers::Const) == 0) {
|
||||||
CXXMethodDecl *OldMD = dyn_cast_or_null<CXXMethodDecl>(OldDecl);
|
CXXMethodDecl *OldMD = 0;
|
||||||
if (FunctionTemplateDecl *OldTD =
|
if (OldDecl)
|
||||||
dyn_cast_or_null<FunctionTemplateDecl>(OldDecl))
|
OldMD = dyn_cast<CXXMethodDecl>(OldDecl->getAsFunction());
|
||||||
OldMD = dyn_cast<CXXMethodDecl>(OldTD->getTemplatedDecl());
|
|
||||||
if (!OldMD || !OldMD->isStatic()) {
|
if (!OldMD || !OldMD->isStatic()) {
|
||||||
const FunctionProtoType *FPT =
|
const FunctionProtoType *FPT =
|
||||||
MD->getType()->castAs<FunctionProtoType>();
|
MD->getType()->castAs<FunctionProtoType>();
|
||||||
|
@ -9699,24 +9691,15 @@ void Sema::computeNRVO(Stmt *Body, FunctionScopeInfo *Scope) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Sema::canSkipFunctionBody(Decl *D) {
|
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
|
// 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
|
// constexpr, since we may need to evaluate its body in order to parse the
|
||||||
// rest of the file.
|
// rest of the file.
|
||||||
// We cannot skip the body of a function with an undeduced return type,
|
// We cannot skip the body of a function with an undeduced return type,
|
||||||
// because any callers of that function need to know the 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) {
|
Decl *Sema::ActOnSkippedFunctionBody(Decl *Decl) {
|
||||||
|
@ -9733,12 +9716,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *D, Stmt *BodyArg) {
|
||||||
|
|
||||||
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
||||||
bool IsInstantiation) {
|
bool IsInstantiation) {
|
||||||
FunctionDecl *FD = 0;
|
FunctionDecl *FD = dcl ? dcl->getAsFunction() : 0;
|
||||||
FunctionTemplateDecl *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(dcl);
|
|
||||||
if (FunTmpl)
|
|
||||||
FD = FunTmpl->getTemplatedDecl();
|
|
||||||
else
|
|
||||||
FD = dyn_cast_or_null<FunctionDecl>(dcl);
|
|
||||||
|
|
||||||
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
|
sema::AnalysisBasedWarnings::Policy WP = AnalysisWarnings.getDefaultPolicy();
|
||||||
sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
|
sema::AnalysisBasedWarnings::Policy *ActivePolicy = 0;
|
||||||
|
|
|
@ -7242,13 +7242,7 @@ bool Sema::CheckUsingShadowDecl(UsingDecl *Using, NamedDecl *Orig,
|
||||||
if (FoundEquivalentDecl)
|
if (FoundEquivalentDecl)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (Target->isFunctionOrFunctionTemplate()) {
|
if (FunctionDecl *FD = Target->getAsFunction()) {
|
||||||
FunctionDecl *FD;
|
|
||||||
if (isa<FunctionTemplateDecl>(Target))
|
|
||||||
FD = cast<FunctionTemplateDecl>(Target)->getTemplatedDecl();
|
|
||||||
else
|
|
||||||
FD = cast<FunctionDecl>(Target);
|
|
||||||
|
|
||||||
NamedDecl *OldDecl = 0;
|
NamedDecl *OldDecl = 0;
|
||||||
switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) {
|
switch (CheckOverload(0, FD, Previous, OldDecl, /*IsForUsingDecl*/ true)) {
|
||||||
case Ovl_Overload:
|
case Ovl_Overload:
|
||||||
|
|
|
@ -2320,11 +2320,7 @@ void Sema::FindAssociatedClassesAndNamespaces(
|
||||||
for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end();
|
for (UnresolvedSetIterator I = ULE->decls_begin(), E = ULE->decls_end();
|
||||||
I != E; ++I) {
|
I != E; ++I) {
|
||||||
// Look through any using declarations to find the underlying function.
|
// Look through any using declarations to find the underlying function.
|
||||||
NamedDecl *Fn = (*I)->getUnderlyingDecl();
|
FunctionDecl *FDecl = (*I)->getUnderlyingDecl()->getAsFunction();
|
||||||
|
|
||||||
FunctionDecl *FDecl = dyn_cast<FunctionDecl>(Fn);
|
|
||||||
if (!FDecl)
|
|
||||||
FDecl = cast<FunctionTemplateDecl>(Fn)->getTemplatedDecl();
|
|
||||||
|
|
||||||
// Add the classes and namespaces associated with the parameter
|
// Add the classes and namespaces associated with the parameter
|
||||||
// types and return type of this function.
|
// types and return type of this function.
|
||||||
|
@ -2814,14 +2810,8 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
|
||||||
// operator template, but not both.
|
// operator template, but not both.
|
||||||
if (FoundRaw && FoundTemplate) {
|
if (FoundRaw && FoundTemplate) {
|
||||||
Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
|
Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
|
||||||
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I) {
|
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
|
||||||
Decl *D = *I;
|
NoteOverloadCandidate((*I)->getUnderlyingDecl()->getAsFunction());
|
||||||
if (UsingShadowDecl *USD = dyn_cast<UsingShadowDecl>(D))
|
|
||||||
D = USD->getTargetDecl();
|
|
||||||
if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(D))
|
|
||||||
D = FunTmpl->getTemplatedDecl();
|
|
||||||
NoteOverloadCandidate(cast<FunctionDecl>(D));
|
|
||||||
}
|
|
||||||
return LOLR_Error;
|
return LOLR_Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2853,14 +2843,8 @@ void ADLResult::insert(NamedDecl *New) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, decide which is a more recent redeclaration.
|
// Otherwise, decide which is a more recent redeclaration.
|
||||||
FunctionDecl *OldFD, *NewFD;
|
FunctionDecl *OldFD = Old->getAsFunction();
|
||||||
if (isa<FunctionTemplateDecl>(New)) {
|
FunctionDecl *NewFD = New->getAsFunction();
|
||||||
OldFD = cast<FunctionTemplateDecl>(Old)->getTemplatedDecl();
|
|
||||||
NewFD = cast<FunctionTemplateDecl>(New)->getTemplatedDecl();
|
|
||||||
} else {
|
|
||||||
OldFD = cast<FunctionDecl>(Old);
|
|
||||||
NewFD = cast<FunctionDecl>(New);
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionDecl *Cursor = NewFD;
|
FunctionDecl *Cursor = NewFD;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -3065,8 +3049,8 @@ NamedDecl *VisibleDeclsRecord::checkHidden(NamedDecl *ND) {
|
||||||
// Functions and function templates in the same scope overload
|
// Functions and function templates in the same scope overload
|
||||||
// rather than hide. FIXME: Look for hiding based on function
|
// rather than hide. FIXME: Look for hiding based on function
|
||||||
// signatures!
|
// signatures!
|
||||||
if ((*I)->isFunctionOrFunctionTemplate() &&
|
if ((*I)->getUnderlyingDecl()->isFunctionOrFunctionTemplate() &&
|
||||||
ND->isFunctionOrFunctionTemplate() &&
|
ND->getUnderlyingDecl()->isFunctionOrFunctionTemplate() &&
|
||||||
SM == ShadowMaps.rbegin())
|
SM == ShadowMaps.rbegin())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -930,24 +930,15 @@ Sema::CheckOverload(Scope *S, FunctionDecl *New, const LookupResult &Old,
|
||||||
(OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() &&
|
(OldIsUsingDecl || NewIsUsingDecl) && CurContext->isRecord() &&
|
||||||
!New->getFriendObjectKind();
|
!New->getFriendObjectKind();
|
||||||
|
|
||||||
if (FunctionTemplateDecl *OldT = dyn_cast<FunctionTemplateDecl>(OldD)) {
|
if (FunctionDecl *OldF = OldD->getAsFunction()) {
|
||||||
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 (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
|
if (!IsOverload(New, OldF, UseMemberUsingDeclRules)) {
|
||||||
if (UseMemberUsingDeclRules && OldIsUsingDecl) {
|
if (UseMemberUsingDeclRules && OldIsUsingDecl) {
|
||||||
HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
|
HideUsingShadowDecl(S, cast<UsingShadowDecl>(*I));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!shouldLinkPossiblyHiddenDecl(*I, New))
|
if (!isa<FunctionTemplateDecl>(OldD) &&
|
||||||
|
!shouldLinkPossiblyHiddenDecl(*I, New))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Match = *I;
|
Match = *I;
|
||||||
|
|
|
@ -6267,13 +6267,9 @@ unsigned clang_CXXMethod_isPureVirtual(CXCursor C) {
|
||||||
if (!clang_isDeclaration(C.kind))
|
if (!clang_isDeclaration(C.kind))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const CXXMethodDecl *Method = 0;
|
|
||||||
const Decl *D = cxcursor::getCursorDecl(C);
|
const Decl *D = cxcursor::getCursorDecl(C);
|
||||||
if (const FunctionTemplateDecl *FunTmpl =
|
const CXXMethodDecl *Method =
|
||||||
dyn_cast_or_null<FunctionTemplateDecl>(D))
|
D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : 0;
|
||||||
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
|
|
||||||
else
|
|
||||||
Method = dyn_cast_or_null<CXXMethodDecl>(D);
|
|
||||||
return (Method && Method->isVirtual() && Method->isPure()) ? 1 : 0;
|
return (Method && Method->isVirtual() && Method->isPure()) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6281,13 +6277,9 @@ unsigned clang_CXXMethod_isStatic(CXCursor C) {
|
||||||
if (!clang_isDeclaration(C.kind))
|
if (!clang_isDeclaration(C.kind))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const CXXMethodDecl *Method = 0;
|
|
||||||
const Decl *D = cxcursor::getCursorDecl(C);
|
const Decl *D = cxcursor::getCursorDecl(C);
|
||||||
if (const FunctionTemplateDecl *FunTmpl =
|
const CXXMethodDecl *Method =
|
||||||
dyn_cast_or_null<FunctionTemplateDecl>(D))
|
D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : 0;
|
||||||
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
|
|
||||||
else
|
|
||||||
Method = dyn_cast_or_null<CXXMethodDecl>(D);
|
|
||||||
return (Method && Method->isStatic()) ? 1 : 0;
|
return (Method && Method->isStatic()) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6295,13 +6287,9 @@ unsigned clang_CXXMethod_isVirtual(CXCursor C) {
|
||||||
if (!clang_isDeclaration(C.kind))
|
if (!clang_isDeclaration(C.kind))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
const CXXMethodDecl *Method = 0;
|
|
||||||
const Decl *D = cxcursor::getCursorDecl(C);
|
const Decl *D = cxcursor::getCursorDecl(C);
|
||||||
if (const FunctionTemplateDecl *FunTmpl =
|
const CXXMethodDecl *Method =
|
||||||
dyn_cast_or_null<FunctionTemplateDecl>(D))
|
D ? dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction()) : 0;
|
||||||
Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl());
|
|
||||||
else
|
|
||||||
Method = dyn_cast_or_null<CXXMethodDecl>(D);
|
|
||||||
return (Method && Method->isVirtual()) ? 1 : 0;
|
return (Method && Method->isVirtual()) ? 1 : 0;
|
||||||
}
|
}
|
||||||
} // end: extern "C"
|
} // end: extern "C"
|
||||||
|
|
Loading…
Reference in New Issue