forked from OSchip/llvm-project
[modules] When we see a definition of a function for which we already have a
non-visible definition, skip the new definition to avoid ending up with a function with multiple definitions. llvm-svn: 245664
This commit is contained in:
parent
772527c57b
commit
b9fa99649b
|
@ -1236,6 +1236,7 @@ private:
|
|||
ParsingDeclSpec &DS,
|
||||
AccessSpecifier AS);
|
||||
|
||||
void SkipFunctionBody();
|
||||
Decl *ParseFunctionDefinition(ParsingDeclarator &D,
|
||||
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
|
||||
LateParsedAttrList *LateParsedAttrs = nullptr);
|
||||
|
|
|
@ -1440,6 +1440,12 @@ public:
|
|||
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
|
||||
//
|
||||
|
||||
struct SkipBodyInfo {
|
||||
SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
|
||||
bool ShouldSkip;
|
||||
NamedDecl *Previous;
|
||||
};
|
||||
|
||||
/// List of decls defined in a function prototype. This contains EnumConstants
|
||||
/// that incorrectly end up in translation unit scope because there is no
|
||||
/// function to pin them on. ActOnFunctionDeclarator reads this list and patches
|
||||
|
@ -1705,11 +1711,14 @@ public:
|
|||
|
||||
void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
|
||||
SourceLocation LocAfterDecls);
|
||||
void CheckForFunctionRedefinition(FunctionDecl *FD,
|
||||
const FunctionDecl *EffectiveDefinition =
|
||||
nullptr);
|
||||
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
|
||||
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
|
||||
void CheckForFunctionRedefinition(
|
||||
FunctionDecl *FD, const FunctionDecl *EffectiveDefinition = nullptr,
|
||||
SkipBodyInfo *SkipBody = nullptr);
|
||||
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D,
|
||||
MultiTemplateParamsArg TemplateParamLists,
|
||||
SkipBodyInfo *SkipBody = nullptr);
|
||||
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
|
||||
SkipBodyInfo *SkipBody = nullptr);
|
||||
void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
|
||||
bool isObjCMethodDecl(Decl *D) {
|
||||
return D && isa<ObjCMethodDecl>(D);
|
||||
|
@ -1851,12 +1860,6 @@ public:
|
|||
TUK_Friend // Friend declaration: 'friend struct foo;'
|
||||
};
|
||||
|
||||
struct SkipBodyInfo {
|
||||
SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
|
||||
bool ShouldSkip;
|
||||
NamedDecl *Previous;
|
||||
};
|
||||
|
||||
Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
|
||||
SourceLocation KWLoc, CXXScopeSpec &SS,
|
||||
IdentifierInfo *Name, SourceLocation NameLoc,
|
||||
|
@ -5630,10 +5633,6 @@ public:
|
|||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
Declarator &D);
|
||||
|
||||
Decl *ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
Declarator &D);
|
||||
|
||||
bool
|
||||
CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
|
||||
TemplateSpecializationKind NewTSK,
|
||||
|
|
|
@ -2614,6 +2614,7 @@ void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
|
|||
}
|
||||
else if (Tok.is(tok::colon)) {
|
||||
ConsumeToken();
|
||||
// FIXME: This is wrong, due to C++11 braced initialization.
|
||||
while (Tok.isNot(tok::l_brace)) {
|
||||
ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
|
||||
ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);
|
||||
|
|
|
@ -1067,10 +1067,17 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
|
|||
|
||||
// Tell the actions module that we have entered a function definition with the
|
||||
// specified Declarator for the function.
|
||||
Decl *Res = TemplateInfo.TemplateParams?
|
||||
Actions.ActOnStartOfFunctionTemplateDef(getCurScope(),
|
||||
*TemplateInfo.TemplateParams, D)
|
||||
: Actions.ActOnStartOfFunctionDef(getCurScope(), D);
|
||||
Sema::SkipBodyInfo SkipBody;
|
||||
Decl *Res = Actions.ActOnStartOfFunctionDef(getCurScope(), D,
|
||||
TemplateInfo.TemplateParams
|
||||
? *TemplateInfo.TemplateParams
|
||||
: MultiTemplateParamsArg(),
|
||||
&SkipBody);
|
||||
|
||||
if (SkipBody.ShouldSkip) {
|
||||
SkipFunctionBody();
|
||||
return Res;
|
||||
}
|
||||
|
||||
// Break out of the ParsingDeclarator context before we parse the body.
|
||||
D.complete(Res);
|
||||
|
@ -1137,6 +1144,28 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
|
|||
return ParseFunctionStatementBody(Res, BodyScope);
|
||||
}
|
||||
|
||||
void Parser::SkipFunctionBody() {
|
||||
if (Tok.is(tok::equal)) {
|
||||
SkipUntil(tok::semi);
|
||||
return;
|
||||
}
|
||||
|
||||
bool IsFunctionTryBlock = Tok.is(tok::kw_try);
|
||||
if (IsFunctionTryBlock)
|
||||
ConsumeToken();
|
||||
|
||||
CachedTokens Skipped;
|
||||
if (ConsumeAndStoreFunctionPrologue(Skipped))
|
||||
SkipMalformedDecl();
|
||||
else {
|
||||
SkipUntil(tok::r_brace);
|
||||
while (IsFunctionTryBlock && Tok.is(tok::kw_catch)) {
|
||||
SkipUntil(tok::l_brace);
|
||||
SkipUntil(tok::r_brace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
|
||||
/// types for a function with a K&R-style identifier list for arguments.
|
||||
void Parser::ParseKNRParamDeclarations(Declarator &D) {
|
||||
|
|
|
@ -2272,9 +2272,17 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
|
|||
const Attr *NewAttribute = NewAttributes[I];
|
||||
|
||||
if (isa<AliasAttr>(NewAttribute)) {
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New))
|
||||
S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def));
|
||||
else {
|
||||
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) {
|
||||
Sema::SkipBodyInfo SkipBody;
|
||||
S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def), &SkipBody);
|
||||
|
||||
// If we're skipping this definition, drop the "alias" attribute.
|
||||
if (SkipBody.ShouldSkip) {
|
||||
NewAttributes.erase(NewAttributes.begin() + I);
|
||||
--E;
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
VarDecl *VD = cast<VarDecl>(New);
|
||||
unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() ==
|
||||
VarDecl::TentativeDefinition
|
||||
|
@ -10398,14 +10406,17 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
|
|||
}
|
||||
}
|
||||
|
||||
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
|
||||
Decl *
|
||||
Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
SkipBodyInfo *SkipBody) {
|
||||
assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
|
||||
assert(D.isFunctionDeclarator() && "Not a function declarator!");
|
||||
Scope *ParentScope = FnBodyScope->getParent();
|
||||
|
||||
D.setFunctionDefinitionKind(FDK_Definition);
|
||||
Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg());
|
||||
return ActOnStartOfFunctionDef(FnBodyScope, DP);
|
||||
Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists);
|
||||
return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
|
||||
}
|
||||
|
||||
void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) {
|
||||
|
@ -10469,7 +10480,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
|
|||
|
||||
void
|
||||
Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
|
||||
const FunctionDecl *EffectiveDefinition) {
|
||||
const FunctionDecl *EffectiveDefinition,
|
||||
SkipBodyInfo *SkipBody) {
|
||||
// Don't complain if we're in GNU89 mode and the previous definition
|
||||
// was an extern inline function.
|
||||
const FunctionDecl *Definition = EffectiveDefinition;
|
||||
|
@ -10481,17 +10493,20 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
|
|||
return;
|
||||
|
||||
// If we don't have a visible definition of the function, and it's inline or
|
||||
// a template, it's OK to form another definition of it.
|
||||
//
|
||||
// FIXME: Should we skip the body of the function and use the old definition
|
||||
// in this case? That may be necessary for functions that return local types
|
||||
// through a deduced return type, or instantiate templates with local types.
|
||||
if (!hasVisibleDefinition(Definition) &&
|
||||
// a template, skip the new definition.
|
||||
if (SkipBody && !hasVisibleDefinition(Definition) &&
|
||||
(Definition->getFormalLinkage() == InternalLinkage ||
|
||||
Definition->isInlined() ||
|
||||
Definition->getDescribedFunctionTemplate() ||
|
||||
Definition->getNumTemplateParameterLists()))
|
||||
Definition->getNumTemplateParameterLists())) {
|
||||
SkipBody->ShouldSkip = true;
|
||||
if (auto *TD = Definition->getDescribedFunctionTemplate())
|
||||
makeMergedDefinitionVisible(TD, FD->getLocation());
|
||||
else
|
||||
makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition),
|
||||
FD->getLocation());
|
||||
return;
|
||||
}
|
||||
|
||||
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
|
||||
Definition->getStorageClass() == SC_Extern)
|
||||
|
@ -10552,7 +10567,8 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
|
|||
}
|
||||
}
|
||||
|
||||
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
|
||||
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
|
||||
SkipBodyInfo *SkipBody) {
|
||||
// Clear the last template instantiation error context.
|
||||
LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
|
||||
|
||||
|
@ -10564,6 +10580,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
|
|||
FD = FunTmpl->getTemplatedDecl();
|
||||
else
|
||||
FD = cast<FunctionDecl>(D);
|
||||
|
||||
// See if this is a redefinition.
|
||||
if (!FD->isLateTemplateParsed()) {
|
||||
CheckForFunctionRedefinition(FD, nullptr, SkipBody);
|
||||
|
||||
// If we're skipping the body, we're done. Don't enter the scope.
|
||||
if (SkipBody && SkipBody->ShouldSkip)
|
||||
return D;
|
||||
}
|
||||
|
||||
// If we are instantiating a generic lambda call operator, push
|
||||
// a LambdaScopeInfo onto the function stack. But use the information
|
||||
// that's already been calculated (ActOnLambdaExpr) to prime the current
|
||||
|
@ -10583,10 +10609,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
|
|||
// Enter a new function scope
|
||||
PushFunctionScope();
|
||||
|
||||
// See if this is a redefinition.
|
||||
if (!FD->isLateTemplateParsed())
|
||||
CheckForFunctionRedefinition(FD);
|
||||
|
||||
// Builtin functions cannot be defined.
|
||||
if (unsigned BuiltinID = FD->getBuiltinID()) {
|
||||
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&
|
||||
|
|
|
@ -6472,24 +6472,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
|
|||
return NewDecl;
|
||||
}
|
||||
|
||||
Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
|
||||
MultiTemplateParamsArg TemplateParameterLists,
|
||||
Declarator &D) {
|
||||
assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
|
||||
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
|
||||
|
||||
if (FTI.hasPrototype) {
|
||||
// FIXME: Diagnose arguments without names in C.
|
||||
}
|
||||
|
||||
Scope *ParentScope = FnBodyScope->getParent();
|
||||
|
||||
D.setFunctionDefinitionKind(FDK_Definition);
|
||||
Decl *DP = HandleDeclarator(ParentScope, D,
|
||||
TemplateParameterLists);
|
||||
return ActOnStartOfFunctionDef(FnBodyScope, DP);
|
||||
}
|
||||
|
||||
/// \brief Strips various properties off an implicit instantiation
|
||||
/// that has just been explicitly specialized.
|
||||
static void StripImplicitInstantiation(NamedDecl *D) {
|
||||
|
|
|
@ -8238,9 +8238,8 @@ void ASTReader::finishPendingActions() {
|
|||
|
||||
// Load the bodies of any functions or methods we've encountered. We do
|
||||
// this now (delayed) so that we can be sure that the declaration chains
|
||||
// have been fully wired up.
|
||||
// FIXME: There seems to be no point in delaying this, it does not depend
|
||||
// on the redecl chains having been wired up.
|
||||
// have been fully wired up (hasBody relies on this).
|
||||
// FIXME: We shouldn't require complete redeclaration chains here.
|
||||
for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
|
||||
PBEnd = PendingBodies.end();
|
||||
PB != PBEnd; ++PB) {
|
||||
|
|
Loading…
Reference in New Issue