From: Argyrios Kyrtzidis Date: Thu, 14 Oct 2010 20:14:25 +0000 (+0000) Subject: Introduce command line option -error-on-deserialized-decl that is accompanied by... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3e78593b1ced32b7e0a97da044213014ee0f6f7c;p=clang Introduce command line option -error-on-deserialized-decl that is accompanied by a name and emits an error if a declaration with this name is deserialized from PCH. This is for testing, to make sure that we don't deserialize stuff needlessly. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116505 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 79dc441075..a175ce5fb4 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -475,6 +475,8 @@ def fno_validate_pch : Flag<"-fno-validate-pch">, HelpText<"Disable validation of precompiled headers">; def dump_deserialized_pch_decls : Flag<"-dump-deserialized-decls">, HelpText<"Dump declarations that are deserialized from PCH, for testing">; +def error_on_deserialized_pch_decl : Separate<"-error-on-deserialized-decl">, + HelpText<"Emit error if a specific declaration is deserialized from PCH, for testing">; def fshort_wchar : Flag<"-fshort-wchar">, HelpText<"Force wchar_t to be a short unsigned int">; def fshort_enums : Flag<"-fshort-enums">, diff --git a/include/clang/Frontend/PreprocessorOptions.h b/include/clang/Frontend/PreprocessorOptions.h index 34b49e1fac..2a540b61df 100644 --- a/include/clang/Frontend/PreprocessorOptions.h +++ b/include/clang/Frontend/PreprocessorOptions.h @@ -15,6 +15,7 @@ #include #include #include +#include namespace llvm { class MemoryBuffer; @@ -50,6 +51,10 @@ public: /// \brief Dump declarations that are deserialized from PCH, for testing. bool DumpDeserializedPCHDecls; + /// \brief This is a set of names for decls that we do not want to be + /// deserialized, and we emit an error if they are; for testing purposes. + std::set DeserializedPCHDeclsToErrorOn; + /// \brief If non-zero, the implicit PCH include is actually a precompiled /// preamble that covers this number of bytes in the main source file. /// diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 8f0cb089ee..3a928a520d 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1409,7 +1409,13 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.UsePredefines = !Args.hasArg(OPT_undef); Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record); Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch); + Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls); + for (arg_iterator it = Args.filtered_begin(OPT_error_on_deserialized_pch_decl), + ie = Args.filtered_end(); it != ie; ++it) { + const Arg *A = *it; + Opts.DeserializedPCHDeclsToErrorOn.insert(A->getValue(Args)); + } if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) { llvm::StringRef Value(A->getValue(Args)); diff --git a/lib/Frontend/FrontendAction.cpp b/lib/Frontend/FrontendAction.cpp index 429b009333..819aa52a50 100644 --- a/lib/Frontend/FrontendAction.cpp +++ b/lib/Frontend/FrontendAction.cpp @@ -51,6 +51,41 @@ public: MacroDefinition *MD) {} }; + /// \brief Checks deserialized declarations and emits error if a name + /// matches one given in command-line using -error-on-deserialized-decl. + class DeserializedDeclsChecker : public ASTDeserializationListener { + ASTContext &Ctx; + std::set NamesToCheck; + ASTDeserializationListener *Previous; + + public: + DeserializedDeclsChecker(ASTContext &Ctx, + const std::set &NamesToCheck, + ASTDeserializationListener *Previous) + : Ctx(Ctx), NamesToCheck(NamesToCheck), Previous(Previous) { } + + virtual void DeclRead(serialization::DeclID ID, const Decl *D) { + if (const NamedDecl *ND = dyn_cast(D)) + if (NamesToCheck.find(ND->getNameAsString()) != NamesToCheck.end()) { + unsigned DiagID + = Ctx.getDiagnostics().getCustomDiagID(Diagnostic::Error, + "%0 was deserialized"); + Ctx.getDiagnostics().Report(Ctx.getFullLoc(D->getLocation()), DiagID) + << ND->getNameAsString(); + } + + if (Previous) + Previous->DeclRead(ID, D); + } + + virtual void SetReader(ASTReader *Reader) {} + virtual void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) {} + virtual void TypeRead(serialization::TypeIdx Idx, QualType T) {} + virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) {} + virtual void MacroDefinitionRead(serialization::MacroID, + MacroDefinition *MD) {} +}; + } // end anonymous namespace FrontendAction::FrontendAction() : Instance(0) {} @@ -154,6 +189,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, Consumer->GetASTDeserializationListener() : 0; if (CI.getPreprocessorOpts().DumpDeserializedPCHDecls) DeserialListener = new DeserializedDeclsDumper(DeserialListener); + if (!CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn.empty()) + DeserialListener = new DeserializedDeclsChecker(CI.getASTContext(), + CI.getPreprocessorOpts().DeserializedPCHDeclsToErrorOn, + DeserialListener); CI.createPCHExternalASTSource( CI.getPreprocessorOpts().ImplicitPCHInclude, CI.getPreprocessorOpts().DisablePCHValidation,