diff options
author | Eli Friedman <eli.friedman@gmail.com> | 2013-09-05 00:02:25 +0000 |
---|---|---|
committer | Eli Friedman <eli.friedman@gmail.com> | 2013-09-05 00:02:25 +0000 |
commit | 276dd188c428d4fb1b3e887fe70a929a71892bf9 (patch) | |
tree | eb49076c4c96fbb6f2efe12c9410cfe119af18e0 | |
parent | 5c30024fd42868e0850cec1e822671187315c8df (diff) | |
download | bcm5719-llvm-276dd188c428d4fb1b3e887fe70a929a71892bf9.tar.gz bcm5719-llvm-276dd188c428d4fb1b3e887fe70a929a71892bf9.zip |
Note when a decl is used in AST files.
When an AST file is built based on another AST file, it can use a decl from
the fist file, and therefore mark the "isUsed" bit. We need to note this in
the AST file so that the bit is set correctly when the second AST file is
loaded.
This patch introduces the distinction between setIsUsed() and markUsed() so
that we don't call into the ASTMutationListener callback when it wouldn't
be appropriate.
Fixes PR16635.
llvm-svn: 190016
-rw-r--r-- | clang/include/clang/AST/ASTMutationListener.h | 5 | ||||
-rw-r--r-- | clang/include/clang/AST/DeclBase.h | 11 | ||||
-rw-r--r-- | clang/include/clang/Serialization/ASTWriter.h | 1 | ||||
-rw-r--r-- | clang/lib/AST/DeclBase.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Frontend/MultiplexConsumer.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 10 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTCommon.h | 3 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderDecl.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriter.cpp | 10 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/System/usr/include/stdio.h | 2 | ||||
-rw-r--r-- | clang/test/Modules/Inputs/pch-used.h | 2 | ||||
-rw-r--r-- | clang/test/Modules/pch-used.m | 8 |
17 files changed, 83 insertions, 28 deletions
diff --git a/clang/include/clang/AST/ASTMutationListener.h b/clang/include/clang/AST/ASTMutationListener.h index ab0d79aecba..6d12a92c61b 100644 --- a/clang/include/clang/AST/ASTMutationListener.h +++ b/clang/include/clang/AST/ASTMutationListener.h @@ -90,6 +90,11 @@ public: const ObjCPropertyDecl *OrigProp, const ObjCCategoryDecl *ClassExt) {} + /// \brief A declaration is marked used which was not previously marked used. + /// + /// \param D the declaration marked used + virtual void DeclarationMarkedUsed(const Decl *D) {} + // NOTE: If new methods are added they should also be added to // MultiplexASTMutationListener. }; diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 71b22ab34c1..2dbfa262c47 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -500,7 +500,16 @@ public: /// whether the function is used. bool isUsed(bool CheckUsedAttr = true) const; - void setUsed(bool U = true) { Used = U; } + /// \brief Set whether the declaration is used, in the sense of odr-use. + /// + /// This should only be used immediately after creating a declaration. + void setIsUsed(bool U) { Used = U; } + + /// \brief Mark the declaration used, in the sense of odr-use. + /// + /// This notifies any mutation listeners in addition to setting a bit + /// indicating the declaration is used. + void markUsed(ASTContext &C); /// \brief Whether this declaration was referenced. bool isReferenced() const; diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 9aa0dd7d927..07fdd062ace 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -743,6 +743,7 @@ public: virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, const ObjCPropertyDecl *OrigProp, const ObjCCategoryDecl *ClassExt); + void DeclarationMarkedUsed(const Decl *D) LLVM_OVERRIDE; }; /// \brief AST and semantic-analysis consumer that generates a diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index e46d671682f..e4d4e77942d 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -291,6 +291,16 @@ bool Decl::isUsed(bool CheckUsedAttr) const { return false; } +void Decl::markUsed(ASTContext &C) { + if (Used) + return; + + if (C.getASTMutationListener()) + C.getASTMutationListener()->DeclarationMarkedUsed(this); + + Used = true; +} + bool Decl::isReferenced() const { if (Referenced) return true; diff --git a/clang/lib/Frontend/MultiplexConsumer.cpp b/clang/lib/Frontend/MultiplexConsumer.cpp index f8ee36a50dc..9cf68a5e9b2 100644 --- a/clang/lib/Frontend/MultiplexConsumer.cpp +++ b/clang/lib/Frontend/MultiplexConsumer.cpp @@ -107,6 +107,8 @@ public: virtual void AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, const ObjCPropertyDecl *OrigProp, const ObjCCategoryDecl *ClassExt); + void DeclarationMarkedUsed(const Decl *D) LLVM_OVERRIDE; + private: std::vector<ASTMutationListener*> Listeners; }; @@ -175,6 +177,10 @@ void MultiplexASTMutationListener::AddedObjCPropertyInClassExtension( for (size_t i = 0, e = Listeners.size(); i != e; ++i) Listeners[i]->AddedObjCPropertyInClassExtension(Prop, OrigProp, ClassExt); } +void MultiplexASTMutationListener::DeclarationMarkedUsed(const Decl *D) { + for (size_t i = 0, e = Listeners.size(); i != e; ++i) + Listeners[i]->DeclarationMarkedUsed(D); +} } // end namespace clang diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 78942afcc9a..68df00dec44 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2739,8 +2739,7 @@ bool Sema::MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old, New->setPure(); // Merge "used" flag. - if (Old->isUsed(false)) - New->setUsed(); + New->setIsUsed(Old->isUsed(false)); // Merge attributes from the parameters. These can mismatch with K&R // declarations. @@ -3050,8 +3049,7 @@ void Sema::MergeVarDecl(VarDecl *New, LookupResult &Previous) { } // Merge "used" flag. - if (Old->isUsed(false)) - New->setUsed(); + New->setIsUsed(Old->isUsed(false)); // Keep a chain of previous declarations. New->setPreviousDeclaration(Old); diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 71b32e570b4..01f3b7cb491 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7951,7 +7951,7 @@ void Sema::DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, SourceLocation Loc = Constructor->getLocation(); Constructor->setBody(new (Context) CompoundStmt(Loc)); - Constructor->setUsed(); + Constructor->markUsed(Context); MarkVTableUsed(CurrentLocation, ClassDecl); if (ASTMutationListener *L = getASTMutationListener()) { @@ -8289,7 +8289,7 @@ void Sema::DefineInheritingConstructor(SourceLocation CurrentLocation, SourceLocation Loc = Constructor->getLocation(); Constructor->setBody(new (Context) CompoundStmt(Loc)); - Constructor->setUsed(); + Constructor->markUsed(Context); MarkVTableUsed(CurrentLocation, ClassDecl); if (ASTMutationListener *L = getASTMutationListener()) { @@ -8421,7 +8421,7 @@ void Sema::DefineImplicitDestructor(SourceLocation CurrentLocation, SourceLocation Loc = Destructor->getLocation(); Destructor->setBody(new (Context) CompoundStmt(Loc)); - Destructor->setUsed(); + Destructor->markUsed(Context); MarkVTableUsed(CurrentLocation, ClassDecl); if (ASTMutationListener *L = getASTMutationListener()) { @@ -9117,7 +9117,7 @@ void Sema::DefineImplicitCopyAssignment(SourceLocation CurrentLocation, if (getLangOpts().CPlusPlus11 && CopyAssignOperator->isImplicit()) diagnoseDeprecatedCopyOperation(*this, CopyAssignOperator, CurrentLocation); - CopyAssignOperator->setUsed(); + CopyAssignOperator->markUsed(Context); SynthesizedFunctionScope Scope(*this, CopyAssignOperator); DiagnosticErrorTrap Trap(Diags); @@ -9562,7 +9562,7 @@ void Sema::DefineImplicitMoveAssignment(SourceLocation CurrentLocation, return; } - MoveAssignOperator->setUsed(); + MoveAssignOperator->markUsed(Context); SynthesizedFunctionScope Scope(*this, MoveAssignOperator); DiagnosticErrorTrap Trap(Diags); @@ -9915,7 +9915,7 @@ void Sema::DefineImplicitCopyConstructor(SourceLocation CurrentLocation, /*isStmtExpr=*/ false).takeAs<Stmt>()); } - CopyConstructor->setUsed(); + CopyConstructor->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(CopyConstructor); } @@ -10101,7 +10101,7 @@ void Sema::DefineImplicitMoveConstructor(SourceLocation CurrentLocation, /*isStmtExpr=*/ false).takeAs<Stmt>()); } - MoveConstructor->setUsed(); + MoveConstructor->markUsed(Context); if (ASTMutationListener *L = getASTMutationListener()) { L->CompletedImplicitDefinition(MoveConstructor); @@ -10119,7 +10119,7 @@ static void markLambdaCallOperatorUsed(Sema &S, CXXRecordDecl *Lambda) { Lambda->lookup( S.Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); CallOperator->setReferenced(); - CallOperator->setUsed(); + CallOperator->markUsed(S.Context); } void Sema::DefineImplicitLambdaToFunctionPointerConversion( @@ -10131,7 +10131,7 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( // Make sure that the lambda call operator is marked used. markLambdaCallOperatorUsed(*this, Lambda); - Conv->setUsed(); + Conv->markUsed(Context); SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); @@ -10150,7 +10150,7 @@ void Sema::DefineImplicitLambdaToFunctionPointerConversion( // Fill in the __invoke function with a dummy implementation. IR generation // will fill in the actual details. - Invoke->setUsed(); + Invoke->markUsed(Context); Invoke->setReferenced(); Invoke->setBody(new (Context) CompoundStmt(Conv->getLocation())); @@ -10164,7 +10164,7 @@ void Sema::DefineImplicitLambdaToBlockPointerConversion( SourceLocation CurrentLocation, CXXConversionDecl *Conv) { - Conv->setUsed(); + Conv->markUsed(Context); SynthesizedFunctionScope Scope(*this, Conv); DiagnosticErrorTrap Trap(Diags); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4fc54bd7f70..464d5877e84 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -9623,7 +9623,7 @@ ExprResult Sema::ActOnUnaryOp(Scope *S, SourceLocation OpLoc, /// ActOnAddrLabel - Parse the GNU address of label extension: "&&foo". ExprResult Sema::ActOnAddrLabel(SourceLocation OpLoc, SourceLocation LabLoc, LabelDecl *TheDecl) { - TheDecl->setUsed(); + TheDecl->markUsed(Context); // Create the AST node. The address of a label always has type 'void*'. return Owned(new (Context) AddrLabelExpr(OpLoc, LabLoc, TheDecl, Context.getPointerType(Context.VoidTy))); @@ -11097,7 +11097,7 @@ void Sema::MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func) { // decl in the middle of a decl chain. We loop to maintain the invariant // that once a decl is used, all decls after it are also used. for (FunctionDecl *F = Func->getMostRecentDecl();; F = F->getPreviousDecl()) { - F->setUsed(true); + F->markUsed(Context); if (F == Func) break; } @@ -11172,7 +11172,7 @@ static ExprResult captureInCapturedRegion(Sema &S, CapturedRegionScopeInfo *RSI, Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal, DeclRefType, VK_LValue, Loc); Var->setReferenced(true); - Var->setUsed(true); + Var->markUsed(S.Context); return Ref; } @@ -11214,7 +11214,7 @@ static ExprResult captureInLambda(Sema &S, LambdaScopeInfo *LSI, Expr *Ref = new (S.Context) DeclRefExpr(Var, RefersToEnclosingLocal, DeclRefType, VK_LValue, Loc); Var->setReferenced(true); - Var->setUsed(true); + Var->markUsed(S.Context); // When the field has array type, create index variables for each // dimension of the array. We use these index variables to subscript @@ -11660,7 +11660,7 @@ static void MarkVarDeclODRUsed(Sema &SemaRef, VarDecl *Var, SemaRef.tryCaptureVariable(Var, Loc); - Var->setUsed(true); + Var->markUsed(SemaRef.Context); } void Sema::UpdateMarkingForLValueToRValue(Expr *E) { diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 242105f789c..3a796ad9025 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1105,7 +1105,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, Lambda->lookup( Context.DeclarationNames.getCXXOperatorName(OO_Call)).front()); CallOperator->setReferenced(); - CallOperator->setUsed(); + CallOperator->markUsed(Context); ExprResult Init = PerformCopyInitialization( InitializedEntity::InitializeBlock(ConvLocation, diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index 861c1c8bd03..ef2202f3374 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -2041,7 +2041,7 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc, if (RangeVarType->isDependentType()) { // The range is implicitly used as a placeholder when it is dependent. - RangeVar->setUsed(); + RangeVar->markUsed(Context); // Deduce any 'auto's in the loop variable as 'DependentTy'. We'll fill // them in properly when we instantiate the loop. @@ -2284,7 +2284,7 @@ StmtResult Sema::ActOnGotoStmt(SourceLocation GotoLoc, SourceLocation LabelLoc, LabelDecl *TheDecl) { getCurFunction()->setHasBranchIntoScope(); - TheDecl->setUsed(); + TheDecl->markUsed(Context); return Owned(new (Context) GotoStmt(TheDecl, GotoLoc, LabelLoc)); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5d6847fdf0e..cc9cb6317a1 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -3352,7 +3352,7 @@ void Sema::BuildVariableInstantiation( NewVar->setAccess(OldVar->getAccess()); if (!OldVar->isStaticDataMember()) { - NewVar->setUsed(OldVar->isUsed(false)); + NewVar->setIsUsed(OldVar->isUsed(false)); NewVar->setReferenced(OldVar->isReferenced()); } diff --git a/clang/lib/Serialization/ASTCommon.h b/clang/lib/Serialization/ASTCommon.h index fa3ef58a1c0..ef81e690324 100644 --- a/clang/lib/Serialization/ASTCommon.h +++ b/clang/lib/Serialization/ASTCommon.h @@ -26,7 +26,8 @@ enum DeclUpdateKind { UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER, - UPD_CXX_DEDUCED_RETURN_TYPE + UPD_CXX_DEDUCED_RETURN_TYPE, + UPD_DECL_MARKED_USED }; TypeIdx TypeIdxFromBuiltin(const BuiltinType *BT); diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index 67ca94bbf8e..b16966530e8 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -377,7 +377,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->setAttrsImpl(Attrs, Reader.getContext()); } D->setImplicit(Record[Idx++]); - D->setUsed(Record[Idx++]); + D->setIsUsed(Record[Idx++]); D->setReferenced(Record[Idx++]); D->setTopLevelDeclInObjCContainer(Record[Idx++]); D->setAccess((AccessSpecifier)Record[Idx++]); @@ -2838,6 +2838,11 @@ void ASTDeclReader::UpdateDecl(Decl *D, ModuleFile &ModuleFile, FD, Reader.readType(ModuleFile, Record, Idx)); break; } + + case UPD_DECL_MARKED_USED: { + D->markUsed(Reader.getContext()); + break; + } } } } diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index f8e8b5d7ada..28a5a423fdf 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4314,6 +4314,7 @@ void ASTWriter::ResolveDeclUpdatesBlocks() { break; case UPD_CXX_INSTANTIATED_STATIC_DATA_MEMBER: + case UPD_DECL_MARKED_USED: ++Idx; break; @@ -5370,3 +5371,12 @@ void ASTWriter::AddedObjCPropertyInClassExtension(const ObjCPropertyDecl *Prop, RewriteDecl(D); } + +void ASTWriter::DeclarationMarkedUsed(const Decl *D) { + assert(!WritingAST && "Already writing the AST!"); + if (!D->isFromASTFile()) + return; + + UpdateRecord &Record = DeclUpdates[D]; + Record.push_back(UPD_DECL_MARKED_USED); +} diff --git a/clang/test/Modules/Inputs/System/usr/include/stdio.h b/clang/test/Modules/Inputs/System/usr/include/stdio.h index 9a7b1063032..f41e09c35a4 100644 --- a/clang/test/Modules/Inputs/System/usr/include/stdio.h +++ b/clang/test/Modules/Inputs/System/usr/include/stdio.h @@ -1,3 +1,3 @@ typedef struct { int id; } FILE; int fprintf(FILE*restrict, const char* restrict format, ...); - +extern FILE *__stderrp; diff --git a/clang/test/Modules/Inputs/pch-used.h b/clang/test/Modules/Inputs/pch-used.h new file mode 100644 index 00000000000..60e0097ea90 --- /dev/null +++ b/clang/test/Modules/Inputs/pch-used.h @@ -0,0 +1,2 @@ +@import cstd.stdio; +static inline void SPXTrace() { fprintf(__stderrp, ""); } diff --git a/clang/test/Modules/pch-used.m b/clang/test/Modules/pch-used.m new file mode 100644 index 00000000000..56961ba404c --- /dev/null +++ b/clang/test/Modules/pch-used.m @@ -0,0 +1,8 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: %clang_cc1 -x objective-c-header -emit-pch %S/Inputs/pch-used.h -o %t/pch-used.h.pch -fmodules -fmodules-cache-path=%t/cache -O0 -isystem %S/Inputs/System/usr/include +// RUN: %clang_cc1 %s -include-pch %t/pch-used.h.pch -fmodules -fmodules-cache-path=%t/cache -O0 -isystem %S/Inputs/System/usr/include -emit-llvm -o - | FileCheck %s + +void f() { SPXTrace(); } + +// CHECK: define internal void @SPXTrace |