diff --git a/clang-tools-extra/modularize/CMakeLists.txt b/clang-tools-extra/modularize/CMakeLists.txt index 0d6ccb78cf3f..37ebc70e7c78 100644 --- a/clang-tools-extra/modularize/CMakeLists.txt +++ b/clang-tools-extra/modularize/CMakeLists.txt @@ -7,7 +7,6 @@ set(LLVM_LINK_COMPONENTS add_clang_executable(modularize Modularize.cpp - PreprocessorTracker.cpp ) target_link_libraries(modularize diff --git a/clang-tools-extra/modularize/Modularize.cpp b/clang-tools-extra/modularize/Modularize.cpp index 45d825d44142..d68e855c70be 100644 --- a/clang-tools-extra/modularize/Modularize.cpp +++ b/clang-tools-extra/modularize/Modularize.cpp @@ -90,12 +90,10 @@ #include #include #include -#include "PreprocessorTracker.h" using namespace clang::tooling; using namespace clang; using namespace llvm; -using namespace Modularize; // Option to specify a file name for a list of header files to check. cl::opt @@ -384,14 +382,8 @@ private: class CollectEntitiesConsumer : public ASTConsumer { public: - CollectEntitiesConsumer(EntityMap &Entities, - PreprocessorTracker &preprocessorTracker, - Preprocessor &PP, StringRef InFile) - : Entities(Entities), PPTracker(preprocessorTracker), PP(PP) { - PPTracker.handlePreprocessorEntry(PP, InFile); - } - - ~CollectEntitiesConsumer() { PPTracker.handlePreprocessorExit(); } + CollectEntitiesConsumer(EntityMap &Entities, Preprocessor &PP) + : Entities(Entities), PP(PP) {} virtual void HandleTranslationUnit(ASTContext &Ctx) { SourceManager &SM = Ctx.getSourceManager(); @@ -417,41 +409,33 @@ public: private: EntityMap &Entities; - PreprocessorTracker &PPTracker; Preprocessor &PP; }; class CollectEntitiesAction : public SyntaxOnlyAction { public: - CollectEntitiesAction(EntityMap &Entities, - PreprocessorTracker &preprocessorTracker) - : Entities(Entities), PPTracker(preprocessorTracker) {} + CollectEntitiesAction(EntityMap &Entities) : Entities(Entities) {} protected: virtual clang::ASTConsumer *CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - return new CollectEntitiesConsumer(Entities, PPTracker, - CI.getPreprocessor(), InFile); + return new CollectEntitiesConsumer(Entities, CI.getPreprocessor()); } private: EntityMap &Entities; - PreprocessorTracker &PPTracker; }; class ModularizeFrontendActionFactory : public FrontendActionFactory { public: - ModularizeFrontendActionFactory(EntityMap &Entities, - PreprocessorTracker &preprocessorTracker) - : Entities(Entities), PPTracker(preprocessorTracker) {} + ModularizeFrontendActionFactory(EntityMap &Entities) : Entities(Entities) {} virtual CollectEntitiesAction *create() { - return new CollectEntitiesAction(Entities, PPTracker); + return new CollectEntitiesAction(Entities); } private: EntityMap &Entities; - PreprocessorTracker &PPTracker; }; int main(int argc, const char **argv) { @@ -480,14 +464,10 @@ int main(int argc, const char **argv) { Compilations.reset( new FixedCompilationDatabase(Twine(PathBuf), CC1Arguments)); - // Create preprocessor tracker, to watch for macro and conditional problems. - OwningPtr PPTracker(PreprocessorTracker::create()); - // Parse all of the headers, detecting duplicates. EntityMap Entities; ClangTool Tool(*Compilations, Headers); - int HadErrors = - Tool.run(new ModularizeFrontendActionFactory(Entities, *PPTracker)); + int HadErrors = Tool.run(new ModularizeFrontendActionFactory(Entities)); // Create a place to save duplicate entity locations, separate bins per kind. typedef SmallVector LocationArray; @@ -535,16 +515,6 @@ int main(int argc, const char **argv) { } } - // Complain about macro instance in header files that differ based on how - // they are included. - if (PPTracker->reportInconsistentMacros(errs())) - HadErrors = 1; - - // Complain about preprocessor conditional directives in header files that - // differ based on how they are included. - if (PPTracker->reportInconsistentConditionals(errs())) - HadErrors = 1; - // Complain about any headers that have contents that differ based on how // they are included. // FIXME: Could we provide information about which preprocessor conditionals @@ -560,7 +530,7 @@ int main(int argc, const char **argv) { HadErrors = 1; errs() << "error: header '" << H->first->getName() - << "' has different contents depending on how it was included.\n"; + << "' has different contents depending on how it was included\n"; for (unsigned I = 0, N = H->second.size(); I != N; ++I) { errs() << "note: '" << H->second[I].Name << "' in " << H->second[I].Loc.File->getName() << " at " diff --git a/clang-tools-extra/modularize/PreprocessorTracker.cpp b/clang-tools-extra/modularize/PreprocessorTracker.cpp deleted file mode 100644 index 8f2f52e8d77c..000000000000 --- a/clang-tools-extra/modularize/PreprocessorTracker.cpp +++ /dev/null @@ -1,1036 +0,0 @@ -//=- PreprocessorTracker.cpp - Preprocessor tracking -*- C++ -*-=// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------------===// - -#include "clang/Lex/LexDiagnostic.h" -#include "clang/Lex/MacroArgs.h" -#include "clang/Lex/PPCallbacks.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/StringPool.h" -#include "PreprocessorTracker.h" - -namespace Modularize { - -// Forwards. -class PreprocessorTrackerImpl; - -// Some handle types - -// String handle. -typedef llvm::PooledStringPtr StringHandle; - -// Header handle. -typedef int HeaderHandle; -const HeaderHandle HeaderHandleInvalid = -1; - -// Header inclusion path handle. -typedef int InclusionPathHandle; -const InclusionPathHandle InclusionPathHandleInvalid = -1; - -// Some utility functions. - -// Get a "file:line:column" source location string. -static std::string getSourceLocationString(clang::Preprocessor &PP, - clang::SourceLocation Loc) { - if (Loc.isInvalid()) - return std::string("(none)"); - else - return Loc.printToString(PP.getSourceManager()); -} - -// Get just the file name from a source location. -static std::string getSourceLocationFile(clang::Preprocessor &PP, - clang::SourceLocation Loc) { - std::string Source(getSourceLocationString(PP, Loc)); - size_t Offset = Source.find(':', 2); - if (Offset == std::string::npos) - return Source; - return Source.substr(0, Offset); -} - -// Get just the line and column from a source location. -static void getSourceLocationLineAndColumn(clang::Preprocessor &PP, - clang::SourceLocation Loc, int &Line, - int &Column) { - clang::PresumedLoc PLoc = PP.getSourceManager().getPresumedLoc(Loc); - if (PLoc.isInvalid()) { - Line = 0; - Column = 0; - return; - } - Line = PLoc.getLine(); - Column = PLoc.getColumn(); -} - -// Retrieve source snippet from file image. -std::string getSourceString(clang::Preprocessor &PP, clang::SourceRange Range) { - clang::SourceLocation BeginLoc = Range.getBegin(); - clang::SourceLocation EndLoc = Range.getEnd(); - const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc); - const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc); - size_t Length = EndPtr - BeginPtr; - return llvm::StringRef(BeginPtr, Length).trim().str(); -} - -// Retrieve source line from file image. -std::string getSourceLine(clang::Preprocessor &PP, clang::SourceLocation Loc) { - const llvm::MemoryBuffer *MemBuffer = - PP.getSourceManager().getBuffer(PP.getSourceManager().getFileID(Loc)); - const char *Buffer = MemBuffer->getBufferStart(); - const char *BufferEnd = MemBuffer->getBufferEnd(); - const char *BeginPtr = PP.getSourceManager().getCharacterData(Loc); - const char *EndPtr = BeginPtr; - while (BeginPtr > Buffer) { - if (*BeginPtr == '\n') { - BeginPtr++; - break; - } - BeginPtr--; - } - while (EndPtr < BufferEnd) { - if (*EndPtr == '\n') { - break; - } - EndPtr++; - } - size_t Length = EndPtr - BeginPtr; - return llvm::StringRef(BeginPtr, Length).str(); -} - -// Get the string for the Unexpanded macro instance. -// The soureRange is expected to end at the last token -// for the macro instance, which in the case of a function-style -// macro will be a ')', but for an object-style macro, it -// will be the macro name itself. -std::string getMacroUnexpandedString(clang::SourceRange Range, - clang::Preprocessor &PP, - llvm::StringRef MacroName, - const clang::MacroInfo *MI) { - clang::SourceLocation BeginLoc(Range.getBegin()); - const char *BeginPtr = PP.getSourceManager().getCharacterData(BeginLoc); - size_t Length; - std::string Unexpanded; - if (MI->isFunctionLike()) { - clang::SourceLocation EndLoc(Range.getEnd()); - const char *EndPtr = PP.getSourceManager().getCharacterData(EndLoc) + 1; - Length = (EndPtr - BeginPtr) + 1; // +1 is ')' width. - } else - Length = MacroName.size(); - return llvm::StringRef(BeginPtr, Length).trim().str(); -} - -// Get the expansion for a macro instance, given the information -// provided by PPCallbacks. -std::string getMacroExpandedString(clang::Preprocessor &PP, - llvm::StringRef MacroName, - const clang::MacroInfo *MI, - const clang::MacroArgs *Args) { - std::string Expanded; - // Walk over the macro Tokens. - typedef clang::MacroInfo::tokens_iterator Iter; - for (Iter I = MI->tokens_begin(), E = MI->tokens_end(); I != E; ++I) { - clang::IdentifierInfo *II = I->getIdentifierInfo(); - int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1); - if (ArgNo == -1) { - // This isn't an argument, just add it. - if (II == NULL) - Expanded += PP.getSpelling((*I)); // Not an identifier. - else { - // Token is for an identifier. - std::string Name = II->getName().str(); - // Check for nexted macro references. - clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); - if (MacroInfo != NULL) - Expanded += getMacroExpandedString(PP, Name, MacroInfo, NULL); - else - Expanded += Name; - } - continue; - } - // We get here if it's a function-style macro with arguments. - const clang::Token *ResultArgToks; - const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo); - if (Args->ArgNeedsPreexpansion(ArgTok, PP)) - ResultArgToks = &(const_cast(Args)) - ->getPreExpArgument(ArgNo, MI, PP)[0]; - else - ResultArgToks = ArgTok; // Use non-preexpanded Tokens. - // If the arg token didn't expand into anything, ignore it. - if (ResultArgToks->is(clang::tok::eof)) - continue; - unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks); - // Append the resulting argument expansions. - for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) { - const clang::Token &AT = ResultArgToks[ArgumentIndex]; - clang::IdentifierInfo *II = AT.getIdentifierInfo(); - if (II == NULL) - Expanded += PP.getSpelling(AT); // Not an identifier. - else { - // It's an identifier. Check for further expansion. - std::string Name = II->getName().str(); - clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); - if (MacroInfo != NULL) - Expanded += getMacroExpandedString(PP, Name, MacroInfo, NULL); - else - Expanded += Name; - } - } - } - return Expanded; -} - -// Get the string representing a vector of Tokens. -std::string -getTokensSpellingString(clang::Preprocessor &PP, - llvm::SmallVectorImpl &Tokens) { - std::string Expanded; - // Walk over the macro Tokens. - typedef llvm::SmallVectorImpl::iterator Iter; - for (Iter I = Tokens.begin(), E = Tokens.end(); I != E; ++I) - Expanded += PP.getSpelling(*I); // Not an identifier. - return llvm::StringRef(Expanded).trim().str(); -} - -// Get the expansion for a macro instance, given the information -// provided by PPCallbacks. -std::string getExpandedString(clang::Preprocessor &PP, - llvm::StringRef MacroName, - const clang::MacroInfo *MI, - const clang::MacroArgs *Args) { - std::string Expanded; - // Walk over the macro Tokens. - typedef clang::MacroInfo::tokens_iterator Iter; - for (Iter I = MI->tokens_begin(), E = MI->tokens_end(); I != E; ++I) { - clang::IdentifierInfo *II = I->getIdentifierInfo(); - int ArgNo = (II && Args ? MI->getArgumentNum(II) : -1); - if (ArgNo == -1) { - // This isn't an argument, just add it. - if (II == NULL) - Expanded += PP.getSpelling((*I)); // Not an identifier. - else { - // Token is for an identifier. - std::string Name = II->getName().str(); - // Check for nexted macro references. - clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); - if (MacroInfo != NULL) - Expanded += getMacroExpandedString(PP, Name, MacroInfo, NULL); - else - Expanded += Name; - } - continue; - } - // We get here if it's a function-style macro with arguments. - const clang::Token *ResultArgToks; - const clang::Token *ArgTok = Args->getUnexpArgument(ArgNo); - if (Args->ArgNeedsPreexpansion(ArgTok, PP)) - ResultArgToks = &(const_cast(Args)) - ->getPreExpArgument(ArgNo, MI, PP)[0]; - else - ResultArgToks = ArgTok; // Use non-preexpanded Tokens. - // If the arg token didn't expand into anything, ignore it. - if (ResultArgToks->is(clang::tok::eof)) - continue; - unsigned NumToks = clang::MacroArgs::getArgLength(ResultArgToks); - // Append the resulting argument expansions. - for (unsigned ArgumentIndex = 0; ArgumentIndex < NumToks; ++ArgumentIndex) { - const clang::Token &AT = ResultArgToks[ArgumentIndex]; - clang::IdentifierInfo *II = AT.getIdentifierInfo(); - if (II == NULL) - Expanded += PP.getSpelling(AT); // Not an identifier. - else { - // It's an identifier. Check for further expansion. - std::string Name = II->getName().str(); - clang::MacroInfo *MacroInfo = PP.getMacroInfo(II); - if (MacroInfo != NULL) - Expanded += getMacroExpandedString(PP, Name, MacroInfo, NULL); - else - Expanded += Name; - } - } - } - return Expanded; -} - -// We need some operator overloads for string handles. -bool operator==(const StringHandle &H1, const StringHandle &H2) { - const char *S1 = (H1 ? *H1 : ""); - const char *S2 = (H2 ? *H2 : ""); - int Diff = strcmp(S1, S2); - return Diff == 0; -} -bool operator!=(const StringHandle &H1, const StringHandle &H2) { - const char *S1 = (H1 ? *H1 : ""); - const char *S2 = (H2 ? *H2 : ""); - int Diff = strcmp(S1, S2); - return Diff != 0; -} -bool operator<(const StringHandle &H1, const StringHandle &H2) { - const char *S1 = (H1 ? *H1 : ""); - const char *S2 = (H2 ? *H2 : ""); - int Diff = strcmp(S1, S2); - return Diff < 0; -} -bool operator>(const StringHandle &H1, const StringHandle &H2) { - const char *S1 = (H1 ? *H1 : ""); - const char *S2 = (H2 ? *H2 : ""); - int Diff = strcmp(S1, S2); - return Diff > 0; -} - -// Preprocessor item key. -// -// This class represents a location in a source file, for use -// as a key representing a unique name/file/line/column quadruplet, -// which in this case is used to identify a macro expansion instance, -// but could be used for other things as well. -// The file is a header file handle, the line is a line number, -// and the column is a column number. -class PPItemKey { -public: - PPItemKey(clang::Preprocessor &PP, StringHandle Name, HeaderHandle File, - clang::SourceLocation Loc) - : Name(Name), File(File) { - getSourceLocationLineAndColumn(PP, Loc, Line, Column); - } - PPItemKey(StringHandle Name, HeaderHandle File, int Line, int Column) - : Name(Name), File(File), Line(Line), Column(Column) {} - PPItemKey(const PPItemKey &Other) - : Name(Other.Name), File(Other.File), Line(Other.Line), - Column(Other.Column) {} - PPItemKey() : File(HeaderHandleInvalid), Line(0), Column(0) {} - bool operator==(const PPItemKey &Other) const { - if (Name != Other.Name) - return false; - if (File != Other.File) - return false; - if (Line != Other.Line) - return false; - return Column == Other.Column; - } - bool operator<(const PPItemKey &Other) const { - if (Name < Other.Name) - return true; - else if (Name > Other.Name) - return false; - if (File < Other.File) - return true; - else if (File > Other.File) - return false; - if (Line < Other.Line) - return true; - else if (Line > Other.Line) - return false; - return Column < Other.Column; - } - StringHandle Name; - HeaderHandle File; - int Line; - int Column; -}; - -// Header inclusion path. -class HeaderInclusionPath { -public: - HeaderInclusionPath(std::vector HeaderInclusionPath) - : Path(HeaderInclusionPath) {} - HeaderInclusionPath(const HeaderInclusionPath &Other) : Path(Other.Path) {} - HeaderInclusionPath() {} - std::vector Path; -}; - -// Macro expansion instance. -// -// This class represents an instance of a macro expansion with a -// unique value. It also stores the unique header inclusion paths -// for use in telling the user the nested include path f -class MacroExpansionInstance { -public: - MacroExpansionInstance(StringHandle MacroExpanded, - PPItemKey &DefinitionLocation, - StringHandle DefinitionSourceLine, - InclusionPathHandle H) - : MacroExpanded(MacroExpanded), DefinitionLocation(DefinitionLocation), - DefinitionSourceLine(DefinitionSourceLine) { - InclusionPathHandles.push_back(H); - } - MacroExpansionInstance() {} - - // Check for the presence of a header inclusion path handle entry. - // Return false if not found. - bool haveInclusionPathHandle(InclusionPathHandle H) { - for (std::vector::iterator - I = InclusionPathHandles.begin(), - E = InclusionPathHandles.end(); - I != E; ++I) { - if (*I == H) - return true; - } - return InclusionPathHandleInvalid; - } - // Add a new header inclusion path entry, if not already present. - void addInclusionPathHandle(InclusionPathHandle H) { - if (!haveInclusionPathHandle(H)) - InclusionPathHandles.push_back(H); - } - - // A string representing the macro instance after preprocessing. - StringHandle MacroExpanded; - // A file/line/column triplet representing the macro definition location. - PPItemKey DefinitionLocation; - // A place to save the macro definition line string. - StringHandle DefinitionSourceLine; - // The header inclusion path handles for all the instances. - std::vector InclusionPathHandles; -}; - -// Macro expansion instance tracker. -// -// This class represents one macro expansion, keyed by a PPItemKey. -// It stores a string representing the macro reference in the source, -// and a list of ConditionalExpansionInstances objects representing -// the unique value the condition expands to in instances of the header. -class MacroExpansionTracker { -public: - MacroExpansionTracker(StringHandle MacroUnexpanded, - StringHandle MacroExpanded, - StringHandle InstanceSourceLine, - PPItemKey &DefinitionLocation, - StringHandle DefinitionSourceLine, - InclusionPathHandle InclusionPathHandle) - : MacroUnexpanded(MacroUnexpanded), - InstanceSourceLine(InstanceSourceLine) { - addMacroExpansionInstance(MacroExpanded, DefinitionLocation, - DefinitionSourceLine, InclusionPathHandle); - } - MacroExpansionTracker() {} - - // Find a matching macro expansion instance. - MacroExpansionInstance * - findMacroExpansionInstance(StringHandle MacroExpanded, - PPItemKey &DefinitionLocation) { - for (std::vector::iterator - I = MacroExpansionInstances.begin(), - E = MacroExpansionInstances.end(); - I != E; ++I) { - if ((I->MacroExpanded == MacroExpanded) && - (I->DefinitionLocation == DefinitionLocation)) { - return &*I; // Found. - } - } - return NULL; // Not found. - } - - // Add a macro expansion instance. - void addMacroExpansionInstance(StringHandle MacroExpanded, - PPItemKey &DefinitionLocation, - StringHandle DefinitionSourceLine, - InclusionPathHandle InclusionPathHandle) { - MacroExpansionInstances.push_back( - MacroExpansionInstance(MacroExpanded, DefinitionLocation, - DefinitionSourceLine, InclusionPathHandle)); - } - - // Return true if there is a mismatch. - bool hasMismatch() { return MacroExpansionInstances.size() > 1; } - - // A string representing the macro instance without expansion. - StringHandle MacroUnexpanded; - // A place to save the macro instance source line string. - StringHandle InstanceSourceLine; - // The macro expansion instances. - // If all instances of the macro expansion expand to the same value, - // This vector will only have one instance. - std::vector MacroExpansionInstances; -}; - -// Conditional expansion instance. -// -// This class represents an instance of a macro expansion with a -// unique value. It also stores the unique header inclusion paths -// for use in telling the user the nested include path f -class ConditionalExpansionInstance { -public: - ConditionalExpansionInstance(bool ConditionValue, InclusionPathHandle H) - : ConditionValue(ConditionValue) { - InclusionPathHandles.push_back(H); - } - ConditionalExpansionInstance() {} - - // Check for the presence of a header inclusion path handle entry. - // Return false if not found. - bool haveInclusionPathHandle(InclusionPathHandle H) { - for (std::vector::iterator - I = InclusionPathHandles.begin(), - E = InclusionPathHandles.end(); - I != E; ++I) { - if (*I == H) - return true; - } - return InclusionPathHandleInvalid; - } - // Add a new header inclusion path entry, if not already present. - void addInclusionPathHandle(InclusionPathHandle H) { - if (!haveInclusionPathHandle(H)) - InclusionPathHandles.push_back(H); - } - - // A flag representing the evaluated condition value. - bool ConditionValue; - // The header inclusion path handles for all the instances. - std::vector InclusionPathHandles; -}; - -// Conditional directive instance tracker. -// -// This class represents one conditional directive, keyed by a PPItemKey. -// It stores a string representing the macro reference in the source, -// and a list of MacroExpansionInstance objects representing -// the unique value the macro expands to in instances of the header. -class ConditionalTracker { -public: - ConditionalTracker(clang::tok::PPKeywordKind DirectiveKind, - bool ConditionValue, StringHandle ConditionUnexpanded, - InclusionPathHandle InclusionPathHandle) - : DirectiveKind(DirectiveKind), ConditionUnexpanded(ConditionUnexpanded) { - addConditionalExpansionInstance(ConditionValue, InclusionPathHandle); - } - ConditionalTracker() {} - - // Find a matching condition expansion instance. - ConditionalExpansionInstance * - findConditionalExpansionInstance(bool ConditionValue) { - for (std::vector::iterator - I = ConditionalExpansionInstances.begin(), - E = ConditionalExpansionInstances.end(); - I != E; ++I) { - if (I->ConditionValue == ConditionValue) { - return &*I; // Found. - } - } - return NULL; // Not found. - } - - // Add a conditional expansion instance. - void - addConditionalExpansionInstance(bool ConditionValue, - InclusionPathHandle InclusionPathHandle) { - ConditionalExpansionInstances.push_back( - ConditionalExpansionInstance(ConditionValue, InclusionPathHandle)); - } - - // Return true if there is a mismatch. - bool hasMismatch() { return ConditionalExpansionInstances.size() > 1; } - - // The kind of directive. - clang::tok::PPKeywordKind DirectiveKind; - // A string representing the macro instance without expansion. - StringHandle ConditionUnexpanded; - // The condition expansion instances. - // If all instances of the conditional expression expand to the same value, - // This vector will only have one instance. - std::vector ConditionalExpansionInstances; -}; - -// Preprocessor callbacks for modularize. -// -// This class derives from the Clang PPCallbacks class to track preprocessor -// actions, such as changing files and handling preprocessor directives and -// macro expansions. It has to figure out when a new header file is entered -// and left, as the provided handler is not particularly clear about it. -class PreprocessorCallbacks : public clang::PPCallbacks { -public: - PreprocessorCallbacks(PreprocessorTrackerImpl &ppTracker, - clang::Preprocessor &PP, llvm::StringRef rootHeaderFile) - : PPTracker(ppTracker), PP(PP), RootHeaderFile(rootHeaderFile) {} - ~PreprocessorCallbacks() {} - - // Overidden handlers. - void FileChanged(clang::SourceLocation Loc, - clang::PPCallbacks::FileChangeReason Reason, - clang::SrcMgr::CharacteristicKind FileType, - clang::FileID PrevFID = clang::FileID()); - void MacroExpands(const clang::Token &MacroNameTok, - const clang::MacroDirective *MD, clang::SourceRange Range, - const clang::MacroArgs *Args); - void Defined(const clang::Token &MacroNameTok, - const clang::MacroDirective *MD, clang::SourceRange Range); - void If(clang::SourceLocation Loc, clang::SourceRange ConditionRange, - bool ConditionResult); - void Elif(clang::SourceLocation Loc, clang::SourceRange ConditionRange, - bool ConditionResult, clang::SourceLocation IfLoc); - void Ifdef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, - const clang::MacroDirective *MD); - void Ifndef(clang::SourceLocation Loc, const clang::Token &MacroNameTok, - const clang::MacroDirective *MD); - -private: - PreprocessorTrackerImpl &PPTracker; - clang::Preprocessor &PP; - std::string RootHeaderFile; -}; - -// Preprocessor macro expansion item map types. -typedef std::map MacroExpansionMap; -typedef std::map::iterator -MacroExpansionMapIter; - -// Preprocessor conditional expansion item map types. -typedef std::map ConditionalExpansionMap; -typedef std::map::iterator -ConditionalExpansionMapIter; - -// Preprocessor tracker for modularize. -// -// This class stores information about all the headers processed in the -// course of running modularize. -class PreprocessorTrackerImpl : public PreprocessorTracker { -public: - PreprocessorTrackerImpl() - : CurrentInclusionPathHandle(InclusionPathHandleInvalid) {} - ~PreprocessorTrackerImpl() {} - - // Handle entering a preprocessing session. - void handlePreprocessorEntry(clang::Preprocessor &PP, - llvm::StringRef rootHeaderFile) { - assert((HeaderStack.size() == 0) && "Header stack should be empty."); - pushHeaderHandle(addHeader(rootHeaderFile)); - PP.addPPCallbacks(new PreprocessorCallbacks(*this, PP, rootHeaderFile)); - } - // Handle exiting a preprocessing session. - void handlePreprocessorExit() { HeaderStack.clear(); } - - // Handle entering a header source file. - void handleHeaderEntry(clang::Preprocessor &PP, llvm::StringRef HeaderPath) { - // Ignore and to reduce message clutter. - if (HeaderPath.startswith("<")) - return; - HeaderHandle H = addHeader(HeaderPath); - if (H != getCurrentHeaderHandle()) - pushHeaderHandle(H); - } - // Handle exiting a header source file. - void handleHeaderExit(llvm::StringRef HeaderPath) { - // Ignore and to reduce message clutter. - if (HeaderPath.startswith("<")) - return; - HeaderHandle H = findHeaderHandle(HeaderPath); - if (isHeaderHandleInStack(H)) { - while ((H != getCurrentHeaderHandle()) && (HeaderStack.size() != 0)) - popHeaderHandle(); - } - } - - // Lookup/add string. - StringHandle addString(llvm::StringRef Str) { return Strings.intern(Str); } - - // Get the handle of a header file entry. - // Return HeaderHandleInvalid if not found. - HeaderHandle findHeaderHandle(llvm::StringRef HeaderPath) const { - HeaderHandle H = 0; - for (std::vector::const_iterator I = HeaderPaths.begin(), - E = HeaderPaths.end(); - I != E; ++I, ++H) { - if (**I == HeaderPath) - return H; - } - return HeaderHandleInvalid; - } - - // Add a new header file entry, or return existing handle. - // Return the header handle. - HeaderHandle addHeader(llvm::StringRef HeaderPath) { - std::string canonicalPath(HeaderPath); - std::replace(canonicalPath.begin(), canonicalPath.end(), '\\', '/'); - HeaderHandle H = findHeaderHandle(canonicalPath); - if (H == HeaderHandleInvalid) { - H = HeaderPaths.size(); - HeaderPaths.push_back(addString(canonicalPath)); - } - return H; - } - - // Return a header file path string given its handle. - StringHandle getHeaderFilePath(HeaderHandle H) const { - if ((H >= 0) && (H < (HeaderHandle)HeaderPaths.size())) - return HeaderPaths[H]; - return StringHandle(); - } - - // Returns a handle to the inclusion path. - InclusionPathHandle pushHeaderHandle(HeaderHandle H) { - HeaderStack.push_back(H); - return CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack); - } - // Pops the last header handle from the stack; - void popHeaderHandle() { - // assert((HeaderStack.size() != 0) && "Header stack already empty."); - if (HeaderStack.size() != 0) { - HeaderStack.pop_back(); - CurrentInclusionPathHandle = addInclusionPathHandle(HeaderStack); - } - } - // Get the top handle on the header stack. - HeaderHandle getCurrentHeaderHandle() const { - if (HeaderStack.size() != 0) - return HeaderStack.back(); - return HeaderHandleInvalid; - } - - // Check for presence of header handle in the header stack. - bool isHeaderHandleInStack(HeaderHandle H) const { - for (std::vector::const_iterator I = HeaderStack.begin(), - E = HeaderStack.end(); - I != E; ++I) { - if (*I == H) - return true; - } - return false; - } - - // Get the handle of a header inclusion path entry. - // Return InclusionPathHandleInvalid if not found. - InclusionPathHandle - findInclusionPathHandle(const std::vector &Path) const { - InclusionPathHandle H = 0; - for (std::vector::const_iterator - I = InclusionPaths.begin(), - E = InclusionPaths.end(); - I != E; ++I, ++H) { - if (I->Path == Path) - return H; - } - return HeaderHandleInvalid; - } - // Add a new header inclusion path entry, or return existing handle. - // Return the header inclusion path entry handle. - InclusionPathHandle - addInclusionPathHandle(const std::vector &Path) { - InclusionPathHandle H = findInclusionPathHandle(Path); - if (H == HeaderHandleInvalid) { - H = InclusionPaths.size(); - InclusionPaths.push_back(HeaderInclusionPath(Path)); - } - return H; - } - // Return the current inclusion path handle. - InclusionPathHandle getCurrentInclusionPathHandle() const { - return CurrentInclusionPathHandle; - } - - // Return an inclusion path given its handle. - const std::vector & - getInclusionPath(InclusionPathHandle H) const { - if ((H >= 0) && (H <= (InclusionPathHandle)InclusionPaths.size())) - return InclusionPaths[H].Path; - static std::vector Empty; - return Empty; - } - - // Add a macro expansion instance. - void addMacroExpansionInstance(clang::Preprocessor &PP, HeaderHandle H, - clang::SourceLocation InstanceLoc, - clang::SourceLocation DefinitionLoc, - clang::IdentifierInfo *II, - llvm::StringRef MacroUnexpanded, - llvm::StringRef MacroExpanded, - InclusionPathHandle InclusionPathHandle) { - StringHandle MacroName = addString(II->getName()); - PPItemKey instanceKey(PP, MacroName, H, InstanceLoc); - PPItemKey definitionKey(PP, MacroName, H, DefinitionLoc); - MacroExpansionMapIter I = MacroExpansions.find(instanceKey); - if (I == MacroExpansions.end()) { - std::string instanceSourceLine = - getSourceLocationString(PP, InstanceLoc) + ":\n" + - getSourceLine(PP, InstanceLoc) + "\n"; - std::string definitionSourceLine = - getSourceLocationString(PP, DefinitionLoc) + ":\n" + - getSourceLine(PP, DefinitionLoc) + "\n"; - MacroExpansions[instanceKey] = MacroExpansionTracker( - addString(MacroUnexpanded), addString(MacroExpanded), - addString(instanceSourceLine), definitionKey, - addString(definitionSourceLine), InclusionPathHandle); - } else { - MacroExpansionTracker &CondTracker = I->second; - MacroExpansionInstance *MacroInfo = - CondTracker.findMacroExpansionInstance(addString(MacroExpanded), - definitionKey); - if (MacroInfo != NULL) - MacroInfo->addInclusionPathHandle(InclusionPathHandle); - else { - std::string definitionSourceLine = - getSourceLocationString(PP, DefinitionLoc) + ":\n" + - getSourceLine(PP, DefinitionLoc) + "\n"; - CondTracker.addMacroExpansionInstance( - addString(MacroExpanded), definitionKey, - addString(definitionSourceLine), InclusionPathHandle); - } - } - } - - // Add a conditional expansion instance. - void - addConditionalExpansionInstance(clang::Preprocessor &PP, HeaderHandle H, - clang::SourceLocation InstanceLoc, - clang::tok::PPKeywordKind DirectiveKind, - bool ConditionValue, - llvm::StringRef ConditionUnexpanded, - InclusionPathHandle InclusionPathHandle) { - StringHandle conditionUnexpanded(addString(ConditionUnexpanded)); - PPItemKey instanceKey(PP, conditionUnexpanded, H, InstanceLoc); - ConditionalExpansionMapIter I = ConditionalExpansions.find(instanceKey); - if (I == ConditionalExpansions.end()) { - std::string instanceSourceLine = - getSourceLocationString(PP, InstanceLoc) + ":\n" + - getSourceLine(PP, InstanceLoc) + "\n"; - ConditionalExpansions[instanceKey] = - ConditionalTracker(DirectiveKind, ConditionValue, conditionUnexpanded, - InclusionPathHandle); - } else { - ConditionalTracker &CondTracker = I->second; - ConditionalExpansionInstance *MacroInfo = - CondTracker.findConditionalExpansionInstance(ConditionValue); - if (MacroInfo != NULL) - MacroInfo->addInclusionPathHandle(InclusionPathHandle); - else { - CondTracker.addConditionalExpansionInstance(ConditionValue, - InclusionPathHandle); - } - } - } - - // Report on inconsistent macro instances. - // Returns true if any mismatches. - bool reportInconsistentMacros(llvm::raw_ostream &OS) { - bool returnValue = false; - for (MacroExpansionMapIter I = MacroExpansions.begin(), - E = MacroExpansions.end(); - I != E; ++I) { - const PPItemKey &ItemKey = I->first; - MacroExpansionTracker &MacroExpTracker = I->second; - if (!MacroExpTracker.hasMismatch()) - continue; - returnValue = true; - OS << *MacroExpTracker.InstanceSourceLine; - if (ItemKey.Column > 0) - OS << std::string(ItemKey.Column - 1, ' ') << "^\n"; - OS << "error: Macro instance '" << *MacroExpTracker.MacroUnexpanded - << "' has different values in this header, depending on how it was " - "included.\n"; - for (std::vector::iterator - IMT = MacroExpTracker.MacroExpansionInstances.begin(), - EMT = MacroExpTracker.MacroExpansionInstances.end(); - IMT != EMT; ++IMT) { - MacroExpansionInstance &MacroInfo = *IMT; - OS << " '" << *MacroExpTracker.MacroUnexpanded << "' Expanded to: '" - << *MacroInfo.MacroExpanded - << "' with respect to these inclusion paths:\n"; - for (std::vector::iterator - IIP = MacroInfo.InclusionPathHandles.begin(), - EIP = MacroInfo.InclusionPathHandles.end(); - IIP != EIP; ++IIP) { - const std::vector &ip = getInclusionPath(*IIP); - int Count = (int)ip.size(); - for (int Index = 0; Index < Count; ++Index) { - HeaderHandle H = ip[Index]; - OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H) - << "\n"; - } - } - // For a macro that wasn't defined, we flag it by using the - // instance location. - // If there is a definition... - if (MacroInfo.DefinitionLocation.Line != ItemKey.Line) { - OS << *MacroInfo.DefinitionSourceLine; - if (MacroInfo.DefinitionLocation.Column > 0) - OS << std::string(MacroInfo.DefinitionLocation.Column - 1, ' ') - << "^\n"; - OS << "Macro defined here.\n"; - } else - OS << "(no macro definition)" - << "\n"; - } - } - return returnValue; - } - - // Report on inconsistent conditional instances. - // Returns true if any mismatches. - bool reportInconsistentConditionals(llvm::raw_ostream &OS) { - bool returnValue = false; - for (ConditionalExpansionMapIter I = ConditionalExpansions.begin(), - E = ConditionalExpansions.end(); - I != E; ++I) { - const PPItemKey &ItemKey = I->first; - ConditionalTracker &CondTracker = I->second; - if (!CondTracker.hasMismatch()) - continue; - returnValue = true; - OS << *HeaderPaths[ItemKey.File] << ":" << ItemKey.Line << ":" - << ItemKey.Column << "\n"; - OS << "#" << getDirectiveSpelling(CondTracker.DirectiveKind) << " " - << *CondTracker.ConditionUnexpanded << "\n"; - OS << "^\n"; - OS << "error: Conditional expression instance '" - << *CondTracker.ConditionUnexpanded - << "' has different values in this header, depending on how it was " - "included.\n"; - for (std::vector::iterator - IMT = CondTracker.ConditionalExpansionInstances.begin(), - EMT = CondTracker.ConditionalExpansionInstances.end(); - IMT != EMT; ++IMT) { - ConditionalExpansionInstance &MacroInfo = *IMT; - OS << " '" << *CondTracker.ConditionUnexpanded << "' Expanded to: '" - << (MacroInfo.ConditionValue ? "true" : "false") - << "' with respect to these inclusion paths:\n"; - for (std::vector::iterator - IIP = MacroInfo.InclusionPathHandles.begin(), - EIP = MacroInfo.InclusionPathHandles.end(); - IIP != EIP; ++IIP) { - const std::vector &ip = getInclusionPath(*IIP); - int Count = (int)ip.size(); - for (int Index = 0; Index < Count; ++Index) { - HeaderHandle H = ip[Index]; - OS << std::string((Index * 2) + 4, ' ') << *getHeaderFilePath(H) - << "\n"; - } - } - } - } - return returnValue; - } - - // Get directive spelling. - static const char *getDirectiveSpelling(clang::tok::PPKeywordKind kind) { - switch (kind) { - case clang::tok::pp_if: - return "if"; - case clang::tok::pp_elif: - return "elif"; - case clang::tok::pp_ifdef: - return "ifdef"; - case clang::tok::pp_ifndef: - return "ifndef"; - default: - return "(unknown)"; - } - } - -private: - llvm::StringPool Strings; - std::vector HeaderPaths; - std::vector HeaderStack; - std::vector InclusionPaths; - InclusionPathHandle CurrentInclusionPathHandle; - MacroExpansionMap MacroExpansions; - ConditionalExpansionMap ConditionalExpansions; -}; - -// PreprocessorTracker functions. - -// PreprocessorTracker desctructor. -PreprocessorTracker::~PreprocessorTracker() {} - -// Create instance of PreprocessorTracker. -PreprocessorTracker *PreprocessorTracker::create() { - return new PreprocessorTrackerImpl(); -} - -// Preprocessor callbacks for modularize. - -// Handle file entry/exit. -void PreprocessorCallbacks::FileChanged( - clang::SourceLocation Loc, clang::PPCallbacks::FileChangeReason Reason, - clang::SrcMgr::CharacteristicKind FileType, clang::FileID PrevFID) { - switch (Reason) { - case EnterFile: - PPTracker.handleHeaderEntry(PP, getSourceLocationFile(PP, Loc)); - break; - case ExitFile: - if (PrevFID.isInvalid()) - PPTracker.handleHeaderExit(RootHeaderFile); - else - PPTracker.handleHeaderExit(getSourceLocationFile(PP, Loc)); - break; - case SystemHeaderPragma: - return; - case RenameFile: - return; - default: - return; - } -} - -// Handle macro expansion. -void PreprocessorCallbacks::MacroExpands(const clang::Token &MacroNameTok, - const clang::MacroDirective *MD, - clang::SourceRange Range, - const clang::MacroArgs *Args) { - clang::SourceLocation Loc = Range.getBegin(); - clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); - const clang::MacroInfo *MI = PP.getMacroInfo(II); - std::string MacroName = II->getName().str(); - std::string Unexpanded(getMacroUnexpandedString(Range, PP, MacroName, MI)); - std::string Expanded(getMacroExpandedString(PP, MacroName, MI, Args)); - PPTracker.addMacroExpansionInstance( - PP, PPTracker.getCurrentHeaderHandle(), Loc, MI->getDefinitionLoc(), II, - Unexpanded, Expanded, PPTracker.getCurrentInclusionPathHandle()); -} - -void PreprocessorCallbacks::Defined(const clang::Token &MacroNameTok, - const clang::MacroDirective *MD, - clang::SourceRange Range) { - clang::SourceLocation Loc(Range.getBegin()); - clang::IdentifierInfo *II = MacroNameTok.getIdentifierInfo(); - const clang::MacroInfo *MI = PP.getMacroInfo(II); - std::string MacroName = II->getName().str(); - std::string Unexpanded(getSourceString(PP, Range)); - PPTracker.addMacroExpansionInstance( - PP, PPTracker.getCurrentHeaderHandle(), Loc, - (MI ? MI->getDefinitionLoc() : Loc), II, Unexpanded, - (MI ? "true" : "false"), PPTracker.getCurrentInclusionPathHandle()); -} - -void PreprocessorCallbacks::If(clang::SourceLocation Loc, - clang::SourceRange ConditionRange, - bool ConditionResult) { - std::string Unexpanded(getSourceString(PP, ConditionRange)); - PPTracker.addConditionalExpansionInstance( - PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_if, - ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle()); -} - -void PreprocessorCallbacks::Elif(clang::SourceLocation Loc, - clang::SourceRange ConditionRange, - bool ConditionResult, - clang::SourceLocation IfLoc) { - std::string Unexpanded(getSourceString(PP, ConditionRange)); - PPTracker.addConditionalExpansionInstance( - PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_elif, - ConditionResult, Unexpanded, PPTracker.getCurrentInclusionPathHandle()); -} - -void PreprocessorCallbacks::Ifdef(clang::SourceLocation Loc, - const clang::Token &MacroNameTok, - const clang::MacroDirective *MD) { - bool IsDefined = (MD != 0); - PPTracker.addConditionalExpansionInstance( - PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifdef, - IsDefined, PP.getSpelling(MacroNameTok), - PPTracker.getCurrentInclusionPathHandle()); -} - -void PreprocessorCallbacks::Ifndef(clang::SourceLocation Loc, - const clang::Token &MacroNameTok, - const clang::MacroDirective *MD) { - bool IsNotDefined = (MD == 0); - PPTracker.addConditionalExpansionInstance( - PP, PPTracker.getCurrentHeaderHandle(), Loc, clang::tok::pp_ifndef, - IsNotDefined, PP.getSpelling(MacroNameTok), - PPTracker.getCurrentInclusionPathHandle()); -} -} // end namespace Modularize diff --git a/clang-tools-extra/modularize/PreprocessorTracker.h b/clang-tools-extra/modularize/PreprocessorTracker.h deleted file mode 100644 index 041efb8fa3ee..000000000000 --- a/clang-tools-extra/modularize/PreprocessorTracker.h +++ /dev/null @@ -1,53 +0,0 @@ -//===- PreprocessorTracker.h - Tracks preprocessor activities -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===--------------------------------------------------------------------===// -/// -/// \file -/// \brief Track preprocessor activities for modularize. -/// -//===--------------------------------------------------------------------===// - -#ifndef MODULARIZE_PREPROCESSOR_TRACKER_H -#define MODULARIZE_PREPROCESSOR_TRACKER_H - -#include "clang/Lex/Preprocessor.h" - -namespace Modularize { - -// Preprocessor tracker for modularize. -// -// This class stores information about all the headers processed in the -// course of running modularize. -class PreprocessorTracker { -public: - virtual ~PreprocessorTracker(); - - // Handle entering a preprocessing session. - // (Called after a Preprocessor object is created, but before preprocessing.) - virtual void handlePreprocessorEntry(clang::Preprocessor &PP, - llvm::StringRef RootHeaderFile) = 0; - // Handle exiting a preprocessing session. - // (Called after preprocessing is complete, but before the Preprocessor - // object is destroyed.) - virtual void handlePreprocessorExit() = 0; - - // Report on inconsistent macro instances. - // Returns true if any mismatches. - virtual bool reportInconsistentMacros(llvm::raw_ostream &OS) = 0; - - // Report on inconsistent conditional directive instances. - // Returns true if any mismatches. - virtual bool reportInconsistentConditionals(llvm::raw_ostream &OS) = 0; - - // Create instance of PreprocessorTracker. - static PreprocessorTracker *create(); -}; - -} // end namespace Modularize - -#endif diff --git a/clang-tools-extra/test/modularize/Inputs/InconsistentSubHeader.h b/clang-tools-extra/test/modularize/Inputs/InconsistentSubHeader.h index ab02b2504b88..92e7d0367dca 100644 --- a/clang-tools-extra/test/modularize/Inputs/InconsistentSubHeader.h +++ b/clang-tools-extra/test/modularize/Inputs/InconsistentSubHeader.h @@ -1,18 +1,11 @@ // Set up so TypeInt only defined during InconsistentHeader1.h include. #ifdef SYMBOL1 #define SYMBOL 1 -#define FUNC_STYLE(a, b) a || b #endif #ifdef SYMBOL2 #define SYMBOL 2 -#define FUNC_STYLE(a, b) a &&b #endif #if SYMBOL == 1 typedef int TypeInt; #endif - -int var = FUNC_STYLE(1, 0); - -#if defined(SYMBOL1) -#endif diff --git a/clang-tools-extra/test/modularize/ProblemsInconsistent.modularize b/clang-tools-extra/test/modularize/ProblemsInconsistent.modularize index f2206905105d..2afd28d4ea99 100644 --- a/clang-tools-extra/test/modularize/ProblemsInconsistent.modularize +++ b/clang-tools-extra/test/modularize/ProblemsInconsistent.modularize @@ -4,105 +4,9 @@ Inputs/InconsistentHeader1.h Inputs/InconsistentHeader2.h # CHECK: error: macro 'SYMBOL' defined at multiple locations: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:3:9 -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:7:9 -# CHECK-NEXT: error: macro 'FUNC_STYLE' defined at multiple locations: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:4:9 -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:8:9 -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:15:11: -# CHECK-NEXT: int var = FUNC_STYLE(1, 0); -# CHECK-NEXT: ^ -# CHECK-NEXT: error: Macro instance 'FUNC_STYLE(1, 0);' has different values in this header, depending on how it was included. -# CHECK-NEXT: 'FUNC_STYLE(1, 0);' expanded to: '1||0' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:4:9: -# CHECK-NEXT: #define FUNC_STYLE(a, b) a || b -# CHECK-NEXT: ^ -# CHECK-NEXT: Macro defined here. -# CHECK-NEXT: 'FUNC_STYLE(1, 0);' expanded to: '1&&0' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:8:9: -# CHECK-NEXT: #define FUNC_STYLE(a, b) a &&b -# CHECK-NEXT: ^ -# CHECK-NEXT: Macro defined here. -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:11:5: -# CHECK-NEXT: #if SYMBOL == 1 -# CHECK-NEXT: ^ -# CHECK-NEXT: error: Macro instance 'SYMBOL' has different values in this header, depending on how it was included. -# CHECK-NEXT: 'SYMBOL' expanded to: '1' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:3:9: -# CHECK-NEXT: #define SYMBOL 1 -# CHECK-NEXT: ^ -# CHECK-NEXT: Macro defined here. -# CHECK-NEXT: 'SYMBOL' expanded to: '2' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:7:9: -# CHECK-NEXT: #define SYMBOL 2 -# CHECK-NEXT: ^ -# CHECK-NEXT: Macro defined here. -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:17:5: -# CHECK-NEXT: #if defined(SYMBOL1) -# CHECK-NEXT: ^ -# CHECK-NEXT: error: Macro instance 'defined(SYMBOL1)' has different values in this header, depending on how it was included. -# CHECK-NEXT: 'defined(SYMBOL1)' expanded to: 'true' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h:3:9: -# CHECK-NEXT: #define SYMBOL1 1 -# CHECK-NEXT: ^ -# CHECK-NEXT: Macro defined here. -# CHECK-NEXT: 'defined(SYMBOL1)' expanded to: 'false' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: (no macro definition) -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:11:2 -# CHECK-NEXT: #if SYMBOL == 1 -# CHECK-NEXT: ^ -# CHECK-NEXT: error: Conditional expression instance 'SYMBOL == 1' has different values in this header, depending on how it was included. -# CHECK-NEXT: 'SYMBOL == 1' expanded to: 'true' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: 'SYMBOL == 1' expanded to: 'false' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:2:2 -# CHECK-NEXT: #ifdef SYMBOL1 -# CHECK-NEXT: ^ -# CHECK-NEXT: error: Conditional expression instance 'SYMBOL1' has different values in this header, depending on how it was included. -# CHECK-NEXT: 'SYMBOL1' expanded to: 'true' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: 'SYMBOL1' expanded to: 'false' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:6:2 -# CHECK-NEXT: #ifdef SYMBOL2 -# CHECK-NEXT: ^ -# CHECK-NEXT: error: Conditional expression instance 'SYMBOL2' has different values in this header, depending on how it was included. -# CHECK-NEXT: 'SYMBOL2' expanded to: 'false' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: 'SYMBOL2' expanded to: 'true' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:17:2 -# CHECK-NEXT: #if defined(SYMBOL1) -# CHECK-NEXT: ^ -# CHECK-NEXT: error: Conditional expression instance 'defined(SYMBOL1)' has different values in this header, depending on how it was included. -# CHECK-NEXT: 'defined(SYMBOL1)' expanded to: 'true' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader1.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: 'defined(SYMBOL1)' expanded to: 'false' with respect to these inclusion paths: -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentHeader2.h -# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h -# CHECK-NEXT: error: header '{{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h' has different contents depending on how it was included. +# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:3:9 +# CHECK-NEXT: {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h:6:9 +# CHECK-NEXT: error: header '{{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h' has different contents depending on how it was included # CHECK-NEXT: note: 'SYMBOL' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 3:9 not always provided -# CHECK-NEXT: note: 'FUNC_STYLE' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 4:9 not always provided -# CHECK-NEXT: note: 'SYMBOL' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 7:9 not always provided -# CHECK-NEXT: note: 'FUNC_STYLE' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 8:9 not always provided -# CHECK-NEXT: note: 'TypeInt' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 12:13 not always provided +# CHECK-NEXT: note: 'SYMBOL' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 6:9 not always provided +# CHECK-NEXT: note: 'TypeInt' in {{.*}}{{[/\\]}}Inputs{{[/\\]}}InconsistentSubHeader.h at 10:13 not always provided