r245664 - [modules] When we see a definition of a function for which we already have a
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 20 20:04:33 PDT 2015
Author: rsmith
Date: Thu Aug 20 22:04:33 2015
New Revision: 245664
URL: http://llvm.org/viewvc/llvm-project?rev=245664&view=rev
Log:
[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.
Modified:
cfe/trunk/include/clang/Parse/Parser.h
cfe/trunk/include/clang/Sema/Sema.h
cfe/trunk/lib/Parse/ParseObjc.cpp
cfe/trunk/lib/Parse/Parser.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=245664&r1=245663&r2=245664&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Thu Aug 20 22:04:33 2015
@@ -1236,6 +1236,7 @@ private:
ParsingDeclSpec &DS,
AccessSpecifier AS);
+ void SkipFunctionBody();
Decl *ParseFunctionDefinition(ParsingDeclarator &D,
const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(),
LateParsedAttrList *LateParsedAttrs = nullptr);
Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=245664&r1=245663&r2=245664&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Aug 20 22:04:33 2015
@@ -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,
Modified: cfe/trunk/lib/Parse/ParseObjc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseObjc.cpp?rev=245664&r1=245663&r2=245664&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseObjc.cpp (original)
+++ cfe/trunk/lib/Parse/ParseObjc.cpp Thu Aug 20 22:04:33 2015
@@ -2614,6 +2614,7 @@ void Parser::StashAwayMethodOrFunctionBo
}
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);
Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=245664&r1=245663&r2=245664&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Thu Aug 20 22:04:33 2015
@@ -1067,10 +1067,17 @@ Decl *Parser::ParseFunctionDefinition(Pa
// 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(Pa
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) {
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=245664&r1=245663&r2=245664&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Aug 20 22:04:33 2015
@@ -2272,9 +2272,17 @@ static void checkNewAttributesAfterDef(S
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::ActOnFinishKNRParamDeclaratio
}
}
-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 ShouldWarnAboutMissingProtot
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(Funct
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(CXXMe
}
}
-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(Scop
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(Scop
// 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) &&
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=245664&r1=245663&r2=245664&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Thu Aug 20 22:04:33 2015
@@ -6472,24 +6472,6 @@ Decl *Sema::ActOnTemplateDeclarator(Scop
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) {
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=245664&r1=245663&r2=245664&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Thu Aug 20 22:04:33 2015
@@ -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) {
More information about the cfe-commits
mailing list