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) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits