Skip to content

Commit b9fa996

Browse files
committed
[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
1 parent 772527c commit b9fa996

7 files changed

Lines changed: 92 additions & 59 deletions

File tree

clang/include/clang/Parse/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,6 +1236,7 @@ class Parser : public CodeCompletionHandler {
12361236
ParsingDeclSpec &DS,
12371237
AccessSpecifier AS);
12381238

1239+
void SkipFunctionBody();
12391240
Decl *ParseFunctionDefinition(ParsingDeclarator &D,
12401241
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
12411242
LateParsedAttrList *LateParsedAttrs = nullptr);

clang/include/clang/Sema/Sema.h

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,12 @@ class Sema {
14401440
// Symbol table / Decl tracking callbacks: SemaDecl.cpp.
14411441
//
14421442

1443+
struct SkipBodyInfo {
1444+
SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
1445+
bool ShouldSkip;
1446+
NamedDecl *Previous;
1447+
};
1448+
14431449
/// List of decls defined in a function prototype. This contains EnumConstants
14441450
/// that incorrectly end up in translation unit scope because there is no
14451451
/// function to pin them on. ActOnFunctionDeclarator reads this list and patches
@@ -1705,11 +1711,14 @@ class Sema {
17051711

17061712
void ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
17071713
SourceLocation LocAfterDecls);
1708-
void CheckForFunctionRedefinition(FunctionDecl *FD,
1709-
const FunctionDecl *EffectiveDefinition =
1710-
nullptr);
1711-
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D);
1712-
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D);
1714+
void CheckForFunctionRedefinition(
1715+
FunctionDecl *FD, const FunctionDecl *EffectiveDefinition = nullptr,
1716+
SkipBodyInfo *SkipBody = nullptr);
1717+
Decl *ActOnStartOfFunctionDef(Scope *S, Declarator &D,
1718+
MultiTemplateParamsArg TemplateParamLists,
1719+
SkipBodyInfo *SkipBody = nullptr);
1720+
Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
1721+
SkipBodyInfo *SkipBody = nullptr);
17131722
void ActOnStartOfObjCMethodDef(Scope *S, Decl *D);
17141723
bool isObjCMethodDecl(Decl *D) {
17151724
return D && isa<ObjCMethodDecl>(D);
@@ -1851,12 +1860,6 @@ class Sema {
18511860
TUK_Friend // Friend declaration: 'friend struct foo;'
18521861
};
18531862

1854-
struct SkipBodyInfo {
1855-
SkipBodyInfo() : ShouldSkip(false), Previous(nullptr) {}
1856-
bool ShouldSkip;
1857-
NamedDecl *Previous;
1858-
};
1859-
18601863
Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
18611864
SourceLocation KWLoc, CXXScopeSpec &SS,
18621865
IdentifierInfo *Name, SourceLocation NameLoc,
@@ -5630,10 +5633,6 @@ class Sema {
56305633
MultiTemplateParamsArg TemplateParameterLists,
56315634
Declarator &D);
56325635

5633-
Decl *ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
5634-
MultiTemplateParamsArg TemplateParameterLists,
5635-
Declarator &D);
5636-
56375636
bool
56385637
CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
56395638
TemplateSpecializationKind NewTSK,

clang/lib/Parse/ParseObjc.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2614,6 +2614,7 @@ void Parser::StashAwayMethodOrFunctionBodyTokens(Decl *MDecl) {
26142614
}
26152615
else if (Tok.is(tok::colon)) {
26162616
ConsumeToken();
2617+
// FIXME: This is wrong, due to C++11 braced initialization.
26172618
while (Tok.isNot(tok::l_brace)) {
26182619
ConsumeAndStoreUntil(tok::l_paren, Toks, /*StopAtSemi=*/false);
26192620
ConsumeAndStoreUntil(tok::r_paren, Toks, /*StopAtSemi=*/false);

clang/lib/Parse/Parser.cpp

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,10 +1067,17 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
10671067

10681068
// Tell the actions module that we have entered a function definition with the
10691069
// specified Declarator for the function.
1070-
Decl *Res = TemplateInfo.TemplateParams?
1071-
Actions.ActOnStartOfFunctionTemplateDef(getCurScope(),
1072-
*TemplateInfo.TemplateParams, D)
1073-
: Actions.ActOnStartOfFunctionDef(getCurScope(), D);
1070+
Sema::SkipBodyInfo SkipBody;
1071+
Decl *Res = Actions.ActOnStartOfFunctionDef(getCurScope(), D,
1072+
TemplateInfo.TemplateParams
1073+
? *TemplateInfo.TemplateParams
1074+
: MultiTemplateParamsArg(),
1075+
&SkipBody);
1076+
1077+
if (SkipBody.ShouldSkip) {
1078+
SkipFunctionBody();
1079+
return Res;
1080+
}
10741081

10751082
// Break out of the ParsingDeclarator context before we parse the body.
10761083
D.complete(Res);
@@ -1137,6 +1144,28 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
11371144
return ParseFunctionStatementBody(Res, BodyScope);
11381145
}
11391146

1147+
void Parser::SkipFunctionBody() {
1148+
if (Tok.is(tok::equal)) {
1149+
SkipUntil(tok::semi);
1150+
return;
1151+
}
1152+
1153+
bool IsFunctionTryBlock = Tok.is(tok::kw_try);
1154+
if (IsFunctionTryBlock)
1155+
ConsumeToken();
1156+
1157+
CachedTokens Skipped;
1158+
if (ConsumeAndStoreFunctionPrologue(Skipped))
1159+
SkipMalformedDecl();
1160+
else {
1161+
SkipUntil(tok::r_brace);
1162+
while (IsFunctionTryBlock && Tok.is(tok::kw_catch)) {
1163+
SkipUntil(tok::l_brace);
1164+
SkipUntil(tok::r_brace);
1165+
}
1166+
}
1167+
}
1168+
11401169
/// ParseKNRParamDeclarations - Parse 'declaration-list[opt]' which provides
11411170
/// types for a function with a K&R-style identifier list for arguments.
11421171
void Parser::ParseKNRParamDeclarations(Declarator &D) {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2272,9 +2272,17 @@ static void checkNewAttributesAfterDef(Sema &S, Decl *New, const Decl *Old) {
22722272
const Attr *NewAttribute = NewAttributes[I];
22732273

22742274
if (isa<AliasAttr>(NewAttribute)) {
2275-
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New))
2276-
S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def));
2277-
else {
2275+
if (FunctionDecl *FD = dyn_cast<FunctionDecl>(New)) {
2276+
Sema::SkipBodyInfo SkipBody;
2277+
S.CheckForFunctionRedefinition(FD, cast<FunctionDecl>(Def), &SkipBody);
2278+
2279+
// If we're skipping this definition, drop the "alias" attribute.
2280+
if (SkipBody.ShouldSkip) {
2281+
NewAttributes.erase(NewAttributes.begin() + I);
2282+
--E;
2283+
continue;
2284+
}
2285+
} else {
22782286
VarDecl *VD = cast<VarDecl>(New);
22792287
unsigned Diag = cast<VarDecl>(Def)->isThisDeclarationADefinition() ==
22802288
VarDecl::TentativeDefinition
@@ -10398,14 +10406,17 @@ void Sema::ActOnFinishKNRParamDeclarations(Scope *S, Declarator &D,
1039810406
}
1039910407
}
1040010408

10401-
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D) {
10409+
Decl *
10410+
Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Declarator &D,
10411+
MultiTemplateParamsArg TemplateParameterLists,
10412+
SkipBodyInfo *SkipBody) {
1040210413
assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
1040310414
assert(D.isFunctionDeclarator() && "Not a function declarator!");
1040410415
Scope *ParentScope = FnBodyScope->getParent();
1040510416

1040610417
D.setFunctionDefinitionKind(FDK_Definition);
10407-
Decl *DP = HandleDeclarator(ParentScope, D, MultiTemplateParamsArg());
10408-
return ActOnStartOfFunctionDef(FnBodyScope, DP);
10418+
Decl *DP = HandleDeclarator(ParentScope, D, TemplateParameterLists);
10419+
return ActOnStartOfFunctionDef(FnBodyScope, DP, SkipBody);
1040910420
}
1041010421

1041110422
void Sema::ActOnFinishInlineMethodDef(CXXMethodDecl *D) {
@@ -10469,7 +10480,8 @@ static bool ShouldWarnAboutMissingPrototype(const FunctionDecl *FD,
1046910480

1047010481
void
1047110482
Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
10472-
const FunctionDecl *EffectiveDefinition) {
10483+
const FunctionDecl *EffectiveDefinition,
10484+
SkipBodyInfo *SkipBody) {
1047310485
// Don't complain if we're in GNU89 mode and the previous definition
1047410486
// was an extern inline function.
1047510487
const FunctionDecl *Definition = EffectiveDefinition;
@@ -10481,17 +10493,20 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD,
1048110493
return;
1048210494

1048310495
// If we don't have a visible definition of the function, and it's inline or
10484-
// a template, it's OK to form another definition of it.
10485-
//
10486-
// FIXME: Should we skip the body of the function and use the old definition
10487-
// in this case? That may be necessary for functions that return local types
10488-
// through a deduced return type, or instantiate templates with local types.
10489-
if (!hasVisibleDefinition(Definition) &&
10496+
// a template, skip the new definition.
10497+
if (SkipBody && !hasVisibleDefinition(Definition) &&
1049010498
(Definition->getFormalLinkage() == InternalLinkage ||
1049110499
Definition->isInlined() ||
1049210500
Definition->getDescribedFunctionTemplate() ||
10493-
Definition->getNumTemplateParameterLists()))
10501+
Definition->getNumTemplateParameterLists())) {
10502+
SkipBody->ShouldSkip = true;
10503+
if (auto *TD = Definition->getDescribedFunctionTemplate())
10504+
makeMergedDefinitionVisible(TD, FD->getLocation());
10505+
else
10506+
makeMergedDefinitionVisible(const_cast<FunctionDecl*>(Definition),
10507+
FD->getLocation());
1049410508
return;
10509+
}
1049510510

1049610511
if (getLangOpts().GNUMode && Definition->isInlineSpecified() &&
1049710512
Definition->getStorageClass() == SC_Extern)
@@ -10552,7 +10567,8 @@ static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator,
1055210567
}
1055310568
}
1055410569

10555-
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
10570+
Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
10571+
SkipBodyInfo *SkipBody) {
1055610572
// Clear the last template instantiation error context.
1055710573
LastTemplateInstantiationErrorContext = ActiveTemplateInstantiation();
1055810574

@@ -10564,6 +10580,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
1056410580
FD = FunTmpl->getTemplatedDecl();
1056510581
else
1056610582
FD = cast<FunctionDecl>(D);
10583+
10584+
// See if this is a redefinition.
10585+
if (!FD->isLateTemplateParsed()) {
10586+
CheckForFunctionRedefinition(FD, nullptr, SkipBody);
10587+
10588+
// If we're skipping the body, we're done. Don't enter the scope.
10589+
if (SkipBody && SkipBody->ShouldSkip)
10590+
return D;
10591+
}
10592+
1056710593
// If we are instantiating a generic lambda call operator, push
1056810594
// a LambdaScopeInfo onto the function stack. But use the information
1056910595
// that's already been calculated (ActOnLambdaExpr) to prime the current
@@ -10583,10 +10609,6 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
1058310609
// Enter a new function scope
1058410610
PushFunctionScope();
1058510611

10586-
// See if this is a redefinition.
10587-
if (!FD->isLateTemplateParsed())
10588-
CheckForFunctionRedefinition(FD);
10589-
1059010612
// Builtin functions cannot be defined.
1059110613
if (unsigned BuiltinID = FD->getBuiltinID()) {
1059210614
if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID) &&

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6472,24 +6472,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scope *S,
64726472
return NewDecl;
64736473
}
64746474

6475-
Decl *Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
6476-
MultiTemplateParamsArg TemplateParameterLists,
6477-
Declarator &D) {
6478-
assert(getCurFunctionDecl() == nullptr && "Function parsing confused");
6479-
DeclaratorChunk::FunctionTypeInfo &FTI = D.getFunctionTypeInfo();
6480-
6481-
if (FTI.hasPrototype) {
6482-
// FIXME: Diagnose arguments without names in C.
6483-
}
6484-
6485-
Scope *ParentScope = FnBodyScope->getParent();
6486-
6487-
D.setFunctionDefinitionKind(FDK_Definition);
6488-
Decl *DP = HandleDeclarator(ParentScope, D,
6489-
TemplateParameterLists);
6490-
return ActOnStartOfFunctionDef(FnBodyScope, DP);
6491-
}
6492-
64936475
/// \brief Strips various properties off an implicit instantiation
64946476
/// that has just been explicitly specialized.
64956477
static void StripImplicitInstantiation(NamedDecl *D) {

clang/lib/Serialization/ASTReader.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8238,9 +8238,8 @@ void ASTReader::finishPendingActions() {
82388238

82398239
// Load the bodies of any functions or methods we've encountered. We do
82408240
// this now (delayed) so that we can be sure that the declaration chains
8241-
// have been fully wired up.
8242-
// FIXME: There seems to be no point in delaying this, it does not depend
8243-
// on the redecl chains having been wired up.
8241+
// have been fully wired up (hasBody relies on this).
8242+
// FIXME: We shouldn't require complete redeclaration chains here.
82448243
for (PendingBodiesMap::iterator PB = PendingBodies.begin(),
82458244
PBEnd = PendingBodies.end();
82468245
PB != PBEnd; ++PB) {

0 commit comments

Comments
 (0)