diff options
-rw-r--r-- | AST/Builtins.cpp | 11 | ||||
-rw-r--r-- | AST/TranslationUnit.cpp | 4 | ||||
-rw-r--r-- | Basic/IdentifierTable.cpp | 8 | ||||
-rw-r--r-- | Basic/TargetInfo.cpp | 227 | ||||
-rw-r--r-- | Basic/Targets.cpp | 63 | ||||
-rw-r--r-- | Driver/clang.cpp | 15 | ||||
-rw-r--r-- | Lex/MacroInfo.cpp | 3 | ||||
-rw-r--r-- | Lex/PPExpressions.cpp | 17 | ||||
-rw-r--r-- | Lex/Preprocessor.cpp | 82 | ||||
-rw-r--r-- | NOTES.txt | 120 | ||||
-rw-r--r-- | Sema/SemaDecl.cpp | 9 | ||||
-rw-r--r-- | include/clang/Basic/DiagnosticKinds.def | 13 | ||||
-rw-r--r-- | include/clang/Basic/IdentifierTable.h | 16 | ||||
-rw-r--r-- | include/clang/Basic/TargetInfo.h | 69 | ||||
-rw-r--r-- | include/clang/Basic/TokenKinds.def | 5 | ||||
-rw-r--r-- | include/clang/Lex/MacroInfo.h | 10 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 3 | ||||
-rw-r--r-- | test/Parser/portability.c | 5 |
18 files changed, 60 insertions, 620 deletions
diff --git a/AST/Builtins.cpp b/AST/Builtins.cpp index 9781c5e944..e2bf5ca007 100644 --- a/AST/Builtins.cpp +++ b/AST/Builtins.cpp @@ -40,17 +40,12 @@ void Builtin::Context::InitializeBuiltins(IdentifierTable &Table, for (unsigned i = Builtin::NotBuiltin+1; i != Builtin::FirstTSBuiltin; ++i) Table.get(BuiltinInfo[i].Name).setBuiltinID(i); - // Step #2: handle target builtins. - std::vector<const char *> NonPortableBuiltins; - Target.getTargetBuiltins(TSRecords, NumTSRecords, NonPortableBuiltins); + // Step #2: Get target builtins. + Target.getTargetBuiltins(TSRecords, NumTSRecords); - // Step #2a: Register target-specific builtins. + // Step #3: Register target-specific builtins. for (unsigned i = 0, e = NumTSRecords; i != e; ++i) Table.get(TSRecords[i].Name).setBuiltinID(i+Builtin::FirstTSBuiltin); - - // Step #2b: Mark non-portable builtins as such. - for (unsigned i = 0, e = NonPortableBuiltins.size(); i != e; ++i) - Table.get(NonPortableBuiltins[i]).setNonPortableBuiltin(true); } /// DecodeTypeFromStr - This decodes one type descriptor from Str, advancing the diff --git a/AST/TranslationUnit.cpp b/AST/TranslationUnit.cpp index c00b344ff8..b91448b2d3 100644 --- a/AST/TranslationUnit.cpp +++ b/AST/TranslationUnit.cpp @@ -191,9 +191,7 @@ TranslationUnit* TranslationUnit::Create(llvm::Deserializer& Dezr, { // Read the TargetInfo. llvm::SerializedPtrID PtrID = Dezr.ReadPtrID(); char* triple = Dezr.ReadCStr(NULL,0,true); - std::string Triple(triple); - Dezr.RegisterPtr(PtrID,TargetInfo::CreateTargetInfo(&Triple, - &Triple+1)); + Dezr.RegisterPtr(PtrID,TargetInfo::CreateTargetInfo(std::string(triple))); delete [] triple; } diff --git a/Basic/IdentifierTable.cpp b/Basic/IdentifierTable.cpp index 45d888140a..65e984a0f7 100644 --- a/Basic/IdentifierTable.cpp +++ b/Basic/IdentifierTable.cpp @@ -32,9 +32,7 @@ IdentifierInfo::IdentifierInfo() { HasMacro = false; IsExtension = false; IsPoisoned = false; - IsOtherTargetMacro = false; IsCPPOperatorKeyword = false; - IsNonPortableBuiltin = false; FETokenInfo = 0; } @@ -203,8 +201,6 @@ tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const { CASE( 8, 'u', 'a', unassert); CASE(12, 'i', 'c', include_next); - CASE(13, 'd', 'f', define_target); - CASE(19, 'd', 'f', define_other_target); #undef CASE #undef HASH } @@ -406,9 +402,7 @@ void IdentifierInfo::Emit(llvm::Serializer& S) const { S.EmitBool(hasMacroDefinition()); S.EmitBool(isExtensionToken()); S.EmitBool(isPoisoned()); - S.EmitBool(isOtherTargetMacro()); S.EmitBool(isCPlusPlusOperatorKeyword()); - S.EmitBool(isNonPortableBuiltin()); // FIXME: FETokenInfo } @@ -419,9 +413,7 @@ void IdentifierInfo::Read(llvm::Deserializer& D) { setHasMacroDefinition(D.ReadBool()); setIsExtensionToken(D.ReadBool()); setIsPoisoned(D.ReadBool()); - setIsOtherTargetMacro(D.ReadBool()); setIsCPlusPlusOperatorKeyword(D.ReadBool()); - setNonPortableBuiltin(D.ReadBool()); // FIXME: FETokenInfo } diff --git a/Basic/TargetInfo.cpp b/Basic/TargetInfo.cpp index 15472a473c..8701b38a0f 100644 --- a/Basic/TargetInfo.cpp +++ b/Basic/TargetInfo.cpp @@ -54,167 +54,28 @@ void TargetInfo::getLongDoubleInfo(uint64_t &Size, unsigned &Align, //===----------------------------------------------------------------------===// TargetInfo::~TargetInfo() { - delete PrimaryTarget; - for (unsigned i = 0; i < SecondaryTargets.size(); ++i) - delete SecondaryTargets[i]; + delete Target; } const char* TargetInfo::getTargetTriple() const { - return PrimaryTarget->getTargetTriple(); + return Target->getTargetTriple(); } const char *TargetInfo::getTargetPrefix() const { - return PrimaryTarget->getTargetPrefix(); -} - -/// DiagnoseNonPortability - When a use of a non-portable target feature is -/// used, this method emits the diagnostic and marks the translation unit as -/// non-portable. -void TargetInfo::DiagnoseNonPortability(FullSourceLoc Loc, - unsigned DiagKind) { - NonPortable = true; - if (Diag && Loc.isValid()) Diag->Report(Loc, DiagKind); -} - -/// GetTargetDefineMap - Get the set of target #defines in an associative -/// collection for easy lookup. -static void GetTargetDefineMap(const TargetInfoImpl *Target, - llvm::StringMap<std::string> &Map) { - std::vector<char> Defines; - Defines.reserve(4096); - Target->getTargetDefines(Defines); - - for (const char *DefStr = &Defines[0], *E = DefStr+Defines.size(); - DefStr != E;) { - // Skip the '#define ' portion. - assert(memcmp(DefStr, "#define ", strlen("#define ")) == 0 && - "#define didn't start with #define!"); - DefStr += strlen("#define "); - - // Find the divider between the key and value. - const char *SpacePos = strchr(DefStr, ' '); - - std::string &Entry = Map.GetOrCreateValue(DefStr, SpacePos).getValue(); - - const char *EndPos = strchr(SpacePos+1, '\n'); - Entry = std::string(SpacePos+1, EndPos); - DefStr = EndPos+1; - } + return Target->getTargetPrefix(); } /// getTargetDefines - Appends the target-specific #define values for this /// target set to the specified buffer. void TargetInfo::getTargetDefines(std::vector<char> &Buffer) { - // If we have no secondary targets, be a bit more efficient. - if (SecondaryTargets.empty()) { - PrimaryTarget->getTargetDefines(Buffer); - return; - } - - // This is tricky in the face of secondary targets. Specifically, - // target-specific #defines that are present and identical across all - // secondary targets are turned into #defines, #defines that are present in - // the primary target but are missing or different in the secondary targets - // are turned into #define_target, and #defines that are not defined in the - // primary, but are defined in a secondary are turned into - // #define_other_target. This allows the preprocessor to correctly track uses - // of target-specific macros. - - // Get the set of primary #defines. - llvm::StringMap<std::string> PrimaryDefines; - GetTargetDefineMap(PrimaryTarget, PrimaryDefines); - - // Get the sets of secondary #defines. - llvm::StringMap<std::string> *SecondaryDefines - = new llvm::StringMap<std::string>[SecondaryTargets.size()]; - for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) - GetTargetDefineMap(SecondaryTargets[i], SecondaryDefines[i]); - - // Loop over all defines in the primary target, processing them until we run - // out. - for (llvm::StringMap<std::string>::iterator PDI = - PrimaryDefines.begin(), E = PrimaryDefines.end(); PDI != E; ++PDI) { - std::string DefineName(PDI->getKeyData(), - PDI->getKeyData() + PDI->getKeyLength()); - std::string DefineValue = PDI->getValue(); - - // Check to see whether all secondary targets have this #define and whether - // it is to the same value. Remember if not, but remove the #define from - // their collection in any case if they have it. - bool isPortable = true; - - for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) { - llvm::StringMap<std::string>::iterator I = - SecondaryDefines[i].find(&DefineName[0], - &DefineName[0]+DefineName.size()); - if (I == SecondaryDefines[i].end()) { - // Secondary target doesn't have this #define. - isPortable = false; - } else { - // Secondary target has this define, remember if it disagrees. - if (isPortable) - isPortable = I->getValue() == DefineValue; - // Remove it from the secondary target unconditionally. - SecondaryDefines[i].erase(I); - } - } - - // If this define is non-portable, turn it into #define_target, otherwise - // just use #define. - const char *Command = isPortable ? "#define " : "#define_target "; - Buffer.insert(Buffer.end(), Command, Command+strlen(Command)); - - // Insert "defname defvalue\n". - Buffer.insert(Buffer.end(), DefineName.begin(), DefineName.end()); - Buffer.push_back(' '); - Buffer.insert(Buffer.end(), DefineValue.begin(), DefineValue.end()); - Buffer.push_back('\n'); - } - - // Now that all of the primary target's defines have been handled and removed - // from the secondary target's define sets, go through the remaining secondary - // target's #defines and taint them. - for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) { - llvm::StringMap<std::string> &Defs = SecondaryDefines[i]; - while (!Defs.empty()) { - const char *DefStart = Defs.begin()->getKeyData(); - const char *DefEnd = DefStart + Defs.begin()->getKeyLength(); - - // Insert "#define_other_target defname". - const char *Command = "#define_other_target "; - Buffer.insert(Buffer.end(), Command, Command+strlen(Command)); - Buffer.insert(Buffer.end(), DefStart, DefEnd); - Buffer.push_back('\n'); - - // If any other secondary targets have this same define, remove it from - // them to avoid duplicate #define_other_target directives. - for (unsigned j = i+1; j != e; ++j) { - llvm::StringMap<std::string>::iterator I = - SecondaryDefines[j].find(DefStart, DefEnd); - if (I != SecondaryDefines[j].end()) - SecondaryDefines[j].erase(I); - } - Defs.erase(Defs.begin()); - } - } - - delete[] SecondaryDefines; + Target->getTargetDefines(Buffer); } /// ComputeWCharWidth - Determine the width of the wchar_t type for the primary /// target, diagnosing whether this is non-portable across the secondary /// targets. void TargetInfo::ComputeWCharInfo(FullSourceLoc Loc) { - PrimaryTarget->getWCharInfo(WCharWidth, WCharAlign); - - // Check whether this is portable across the secondary targets if the T-U is - // portable so far. - for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) { - unsigned Width, Align; - SecondaryTargets[i]->getWCharInfo(Width, Align); - if (Width != WCharWidth || Align != WCharAlign) - return DiagnoseNonPortability(Loc, diag::port_wchar_t); - } + Target->getWCharInfo(WCharWidth, WCharAlign); } @@ -222,69 +83,18 @@ void TargetInfo::ComputeWCharInfo(FullSourceLoc Loc) { /// the current primary target, and info about which builtins are non-portable /// across the current set of primary and secondary targets. void TargetInfo::getTargetBuiltins(const Builtin::Info *&Records, - unsigned &NumRecords, - std::vector<const char *> &NPortable) const { + unsigned &NumRecords) const { // Get info about what actual builtins we will expose. - PrimaryTarget->getTargetBuiltins(Records, NumRecords); - if (SecondaryTargets.empty()) return; - - // Compute the set of non-portable builtins. - - // Start by computing a mapping from the primary target's builtins to their - // info records for efficient lookup. - llvm::StringMap<const Builtin::Info*> PrimaryRecs; - for (unsigned i = 0, e = NumRecords; i != e; ++i) { - const char *BIName = Records[i].Name; - PrimaryRecs.GetOrCreateValue(BIName, BIName+strlen(BIName)).getValue() - = Records+i; - } - - for (unsigned i = 0, e = SecondaryTargets.size(); i != e; ++i) { - // Get the builtins for this secondary target. - const Builtin::Info *Records2nd; - unsigned NumRecords2nd; - SecondaryTargets[i]->getTargetBuiltins(Records2nd, NumRecords2nd); - - // Remember all of the secondary builtin names. - std::set<std::string> BuiltinNames2nd; - - for (unsigned j = 0, e = NumRecords2nd; j != e; ++j) { - BuiltinNames2nd.insert(Records2nd[j].Name); - - // Check to see if the primary target has this builtin. - llvm::StringMap<const Builtin::Info*>::iterator I = - PrimaryRecs.find(Records2nd[j].Name, - Records2nd[j].Name+strlen(Records2nd[j].Name)); - if (I != PrimaryRecs.end()) { - const Builtin::Info *PrimBI = I->getValue(); - // If does. If they are not identical, mark the builtin as being - // non-portable. - if (Records2nd[j] != *PrimBI) - NPortable.push_back(PrimBI->Name); - } else { - // The primary target doesn't have this, it is non-portable. - NPortable.push_back(Records2nd[j].Name); - } - } - - // Now that we checked all the secondary builtins, check to see if the - // primary target has any builtins that the secondary one doesn't. If so, - // then those are non-portable. - for (unsigned j = 0, e = NumRecords; j != e; ++j) { - if (!BuiltinNames2nd.count(Records[j].Name)) - NPortable.push_back(Records[j].Name); - } - } + Target->getTargetBuiltins(Records, NumRecords); } /// getVAListDeclaration - Return the declaration to use for /// __builtin_va_list, which is target-specific. const char *TargetInfo::getVAListDeclaration() const { - return PrimaryTarget->getVAListDeclaration(); + return Target->getVAListDeclaration(); } -static void removeGCCRegisterPrefix(const char *&Name) -{ +static void removeGCCRegisterPrefix(const char *&Name) { if (Name[0] == '%' || Name[0] == '#') Name++; } @@ -304,7 +114,7 @@ bool TargetInfo::isValidGCCRegisterName(const char *Name) const { strcmp(Name, "cc") == 0) return true; - PrimaryTarget->getGCCRegNames(Names, NumNames); + Target->getGCCRegNames(Names, NumNames); // If we have a number it maps to an entry in the register name array. if (isdigit(Name[0])) { @@ -324,7 +134,7 @@ bool TargetInfo::isValidGCCRegisterName(const char *Name) const { const TargetInfoImpl::GCCRegAlias *Aliases; unsigned NumAliases; - PrimaryTarget->getGCCRegAliases(Aliases, NumAliases); + Target->getGCCRegAliases(Aliases, NumAliases); for (unsigned i = 0; i < NumAliases; i++) { for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) { if (!Aliases[i].Aliases[j]) @@ -346,7 +156,7 @@ const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const const char * const *Names; unsigned NumNames; - PrimaryTarget->getGCCRegNames(Names, NumNames); + Target->getGCCRegNames(Names, NumNames); // First, check if we have a number. if (isdigit(Name[0])) { @@ -363,7 +173,7 @@ const char *TargetInfo::getNormalizedGCCRegisterName(const char *Name) const const TargetInfoImpl::GCCRegAlias *Aliases; unsigned NumAliases; - PrimaryTarget->getGCCRegAliases(Aliases, NumAliases); + Target->getGCCRegAliases(Aliases, NumAliases); for (unsigned i = 0; i < NumAliases; i++) { for (unsigned j = 0 ; j < llvm::array_lengthof(Aliases[i].Aliases); j++) { if (!Aliases[i].Aliases[j]) @@ -392,7 +202,7 @@ bool TargetInfo::validateOutputConstraint(const char *Name, while (*Name) { switch (*Name) { default: - if (!PrimaryTarget->validateAsmConstraint(*Name, info)) { + if (!Target->validateAsmConstraint(*Name, info)) { // FIXME: This assert is in place temporarily // so we can add more constraints as we hit it. // Eventually, an unknown constraint should just be treated as 'g'. @@ -431,7 +241,7 @@ bool TargetInfo::validateInputConstraint(const char *Name, // Check if matching constraint is out of bounds. if (i >= NumOutputs) return false; - } else if (!PrimaryTarget->validateAsmConstraint(*Name, info)) { + } else if (!Target->validateAsmConstraint(*Name, info)) { // FIXME: This assert is in place temporarily // so we can add more constraints as we hit it. // Eventually, an unknown constraint should just be treated as 'g'. @@ -461,12 +271,11 @@ bool TargetInfo::validateInputConstraint(const char *Name, } std::string TargetInfo::convertConstraint(const char Constraint) const { - return PrimaryTarget->convertConstraint(Constraint); + return Target->convertConstraint(Constraint); } -const char *TargetInfo::getClobbers() const -{ - return PrimaryTarget->getClobbers(); +const char *TargetInfo::getClobbers() const { + return Target->getClobbers(); } diff --git a/Basic/Targets.cpp b/Basic/Targets.cpp index 7d64942b4f..d170fbefb6 100644 --- a/Basic/Targets.cpp +++ b/Basic/Targets.cpp @@ -776,54 +776,27 @@ static inline bool IsX86(const std::string& TT) { TT[4] == '-' && TT[1] - '3' < 6); } -/// CreateTarget - Create the TargetInfoImpl object for the specified target -/// enum value. -static TargetInfoImpl *CreateTarget(const std::string& T) { +/// CreateTargetInfo - Return the target info object for the specified target +/// triple. +TargetInfo* TargetInfo::CreateTargetInfo(const std::string &T) { if (T.find("ppc-") == 0 || T.find("powerpc-") == 0) - return new DarwinPPCTargetInfo(T); - else if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0) - return new DarwinPPC64TargetInfo(T); - else if (T.find("sparc-") == 0) - return new SolarisSparcV8TargetInfo(T); // ugly hack - else if (T.find("x86_64-") == 0) - return new DarwinX86_64TargetInfo(T); - else if (IsX86(T)) - return new DarwinI386TargetInfo(T); - else if (T.find("bogusW16W16-") == 0) // For testing portability. - return new LinuxTargetInfo(T); - else - return NULL; -} - -/// CreateTargetInfo - Return the set of target info objects as specified by -/// the -arch command line option. -TargetInfo* TargetInfo::CreateTargetInfo(const std::string* TriplesStart, - const std::string* TriplesEnd, - Diagnostic *Diags) { - - // Create the primary target and target info. - TargetInfoImpl* PrimaryTarget = CreateTarget(*TriplesStart); - - if (!PrimaryTarget) - return NULL; + return new TargetInfo(new DarwinPPCTargetInfo(T)); - TargetInfo *TI = new TargetInfo(PrimaryTarget, Diags); + if (T.find("ppc64-") == 0 || T.find("powerpc64-") == 0) + return new TargetInfo(new DarwinPPC64TargetInfo(T)); - // Add all secondary targets. - for (const std::string* I=TriplesStart+1; I != TriplesEnd; ++I) { - TargetInfoImpl* SecondaryTarget = CreateTarget(*I); - - if (!SecondaryTarget) { - fprintf (stderr, - "Warning: secondary target '%s' unrecognized.\n", - I->c_str()); - - continue; - } - - TI->AddSecondaryTarget(SecondaryTarget); - } + if (T.find("sparc-") == 0) + return new TargetInfo(new SolarisSparcV8TargetInfo(T)); // ugly hack + + if (T.find("x86_64-") == 0) + return new TargetInfo(new DarwinX86_64TargetInfo(T)); + + if (IsX86(T)) + return new TargetInfo(new DarwinI386TargetInfo(T)); + + if (T.find("bogusW16W16-") == 0) // For testing portability. + return new TargetInfo(new LinuxTargetInfo(T)); - return TI; + return NULL; } diff --git a/Driver/clang.cpp b/Driver/clang.cpp index 5d004977ca..f5790df482 100644 --- a/Driver/clang.cpp +++ b/Driver/clang.cpp @@ -466,7 +466,7 @@ static llvm::cl::opt<std::string> TargetTriple("triple", llvm::cl::desc("Specify target triple (e.g. i686-apple-darwin9).")); -static llvm::cl::list<std::string> +static llvm::cl::opt<std::string> Archs("arch", llvm::cl::desc("Specify target architecture (e.g. i686).")); @@ -518,9 +518,9 @@ static void CreateTargetTriples(std::vector<std::string>& triples) { // host-triple with no archs or using a specified target triple. if (!TargetTriple.getValue().empty() || Archs.empty()) tp.addTriple(Triple); - - for (unsigned i = 0, e = Archs.size(); i !=e; ++i) - tp.addTriple(Archs[i] + "-" + suffix); + + if (!Archs.empty()) + tp.addTriple(Archs + "-" + suffix); } //===----------------------------------------------------------------------===// @@ -1307,14 +1307,9 @@ int main(int argc, char **argv) { // Get information about the targets being compiled for. Note that this // pointer and the TargetInfoImpl objects are never deleted by this toy // driver. - TargetInfo *Target; - - // Create triples, and create the TargetInfo. std::vector<std::string> triples; CreateTargetTriples(triples); - Target = TargetInfo::CreateTargetInfo(&triples[0], - &triples[0]+triples.size(), - &Diags); + TargetInfo *Target = TargetInfo::CreateTargetInfo(triples[0]); if (Target == 0) { fprintf(stderr, "Sorry, I don't know what target this is: %s\n", diff --git a/Lex/MacroInfo.cpp b/Lex/MacroInfo.cpp index 4640e47ce7..de19ff502a 100644 --- a/Lex/MacroInfo.cpp +++ b/Lex/MacroInfo.cpp @@ -20,7 +20,6 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { IsC99Varargs = false; IsGNUVarargs = false; IsBuiltinMacro = false; - IsTargetSpecific = false; IsDisabled = false; IsUsed = true; @@ -32,8 +31,6 @@ MacroInfo::MacroInfo(SourceLocation DefLoc) : Location(DefLoc) { /// this macro in spelling, arguments, and whitespace. This is used to emit /// duplicate definition warnings. This implements the rules in C99 6.10.3. /// -/// Note that this intentionally does not check isTargetSpecific for matching. -/// bool MacroInfo::isIdenticalTo(const MacroInfo &Other, Preprocessor &PP) const { // Check # tokens in replacement, number of args, and various flags all match. if (ReplacementTokens.size() != Other.ReplacementTokens.size() || diff --git a/Lex/PPExpressions.cpp b/Lex/PPExpressions.cpp index 427d95bf36..c56692e1f4 100644 --- a/Lex/PPExpressions.cpp +++ b/Lex/PPExpressions.cpp @@ -108,23 +108,6 @@ static bool EvaluateValue(llvm::APSInt &Result, Token &PeekTok, if (Result != 0 && ValueLive) { MacroInfo *Macro = PP.getMacroInfo(II); Macro->setIsUsed(true); - - // If this is the first use of a target-specific macro, warn about it. - if (Macro->isTargetSpecific()) { - // Don't warn on second use. - Macro->setIsTargetSpecific(false); - PP.getTargetInfo().DiagnoseNonPortability( - PP.getFullLoc(PeekTok.getLocation()), - diag::port_target_macro_use); - } - } else if (ValueLive) { - // Use of a target-specific macro for some other target? If so, warn. - if (II->isOtherTargetMacro()) { - II->setIsOtherTargetMacro(false); // Don't warn on second use. - PP.getTargetInfo().DiagnoseNonPortability( - PP.getFullLoc(PeekTok.getLocation()), - diag::port_target_macro_use); - } } // Consume identifier. diff --git a/Lex/Preprocessor.cpp b/Lex/Preprocessor.cpp index be2ffefaa7..0f6ebabe37 100644 --- a/Lex/Preprocessor.cpp +++ b/Lex/Preprocessor.cpp @@ -808,13 +808,6 @@ bool Preprocessor::HandleMacroExpandedIdentifier(Token &Identifier, return false; } - // If this is the first use of a target-specific macro, warn about it. - if (MI->isTargetSpecific()) { - MI->setIsTargetSpecific(false); // Don't warn on second use. - getTargetInfo().DiagnoseNonPortability(getFullLoc(Identifier.getLocation()), - diag::port_target_macro_use); - } - /// Args - If this is a function-like macro expansion, this contains, /// for each macro argument, the list of tokens that were provided to the /// invocation. @@ -1242,14 +1235,6 @@ void Preprocessor::HandleIdentifier(Token &Identifier) { Identifier.setFlag(Token::DisableExpand); } } - } else if (II.isOtherTargetMacro() && !DisableMacroExpansion) { - // If this identifier is a macro on some other target, emit a diagnostic. - // This diagnosic is only emitted when macro expansion is enabled, because - // the macro would not have been expanded for the other target either. - II.setIsOtherTargetMacro(false); // Don't warn on second use. - getTargetInfo().DiagnoseNonPortability(getFullLoc(Identifier.getLocation()), - diag::port_target_macro_use); - } // C++ 2.11p2: If this is an alternative representation of a C++ operator, @@ -1775,7 +1760,7 @@ TryAgain: // C99 6.10.3 - Macro Replacement. case tok::pp_define: - return HandleDefineDirective(Result, false); + return HandleDefineDirective(Result); case tok::pp_undef: return HandleUndefDirective(Result); @@ -1812,12 +1797,6 @@ TryAgain: case tok::pp_unassert: //isExtension = true; // FIXME: implement #unassert break; - - // clang extensions. - case tok::pp_define_target: - return HandleDefineDirective(Result, true); - case tok::pp_define_other_target: - return HandleDefineOtherTargetDirective(Result); } break; } @@ -2176,11 +2155,8 @@ bool Preprocessor::ReadMacroDefinitionArgList(MacroInfo *MI) { } /// HandleDefineDirective - Implements #define. This consumes the entire macro -/// line then lets the caller lex the next real token. If 'isTargetSpecific' is -/// true, then this is a "#define_target", otherwise this is a "#define". -/// -void Preprocessor::HandleDefineDirective(Token &DefineTok, - bool isTargetSpecific) { +/// line then lets the caller lex the next real token. +void Preprocessor::HandleDefineDirective(Token &DefineTok) { ++NumDefined; Token MacroNameTok; @@ -2196,11 +2172,6 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, // Create the new macro. MacroInfo *MI = new MacroInfo(MacroNameTok.getLocation()); - if (isTargetSpecific) MI->setIsTargetSpecific(); - - // If the identifier is an 'other target' macro, clear this bit. - MacroNameTok.getIdentifierInfo()->setIsOtherTargetMacro(false); - Token Tok; LexUnexpandedToken(Tok); @@ -2337,30 +2308,6 @@ void Preprocessor::HandleDefineDirective(Token &DefineTok, setMacroInfo(MacroNameTok.getIdentifierInfo(), MI); } -/// HandleDefineOtherTargetDirective - Implements #define_other_target. -void Preprocessor::HandleDefineOtherTargetDirective(Token &Tok) { - Token MacroNameTok; - ReadMacroName(MacroNameTok, 1); - - // Error reading macro name? If so, diagnostic already issued. - if (MacroNameTok.is(tok::eom)) - return; - - // Check to see if this is the last token on the #undef line. - CheckEndOfDirective("#define_other_target"); - - // If there is already a macro defined by this name, turn it into a - // target-specific define. - if (MacroInfo *MI = getMacroInfo(MacroNameTok.getIdentifierInfo())) { - MI->setIsTargetSpecific(true); - return; - } - - // Mark the identifier as being a macro on some other target. - MacroNameTok.getIdentifierInfo()->setIsOtherTargetMacro(); -} - - /// HandleUndefDirective - Implements #undef. /// void Preprocessor::HandleUndefDirective(Token &UndefTok) { @@ -2379,9 +2326,6 @@ void Preprocessor::HandleUndefDirective(Token &UndefTok) { // Okay, we finally have a valid identifier to undef. MacroInfo *MI = getMacroInfo(MacroNameTok.getIdentifierInfo()); - // #undef untaints an identifier if it were marked by define_other_target. - MacroNameTok.getIdentifierInfo()->setIsOtherTargetMacro(false); - // If the macro is not defined, this is a noop undef, just return. if (MI == 0) return; @@ -2436,26 +2380,8 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, MacroInfo *MI = getMacroInfo(MII); // If there is a macro, process it. - if (MI) { - // Mark it used. + if (MI) // Mark it used. MI->setIsUsed(true); - - // If this is the first use of a target-specific macro, warn about it. - if (MI->isTargetSpecific()) { - MI->setIsTargetSpecific(false); // Don't warn on second use. - getTargetInfo().DiagnoseNonPortability( - getFullLoc(MacroNameTok.getLocation()), - diag::port_target_macro_use); - } - } else { - // Use of a target-specific macro for some other target? If so, warn. - if (MII->isOtherTargetMacro()) { - MII->setIsOtherTargetMacro(false); // Don't warn on second use. - getTargetInfo().DiagnoseNonPortability( - getFullLoc(MacroNameTok.getLocation()), - diag::port_target_macro_use); - } - } // Should we include the stuff contained by this directive? if (!MI == isIfndef) { @@ -6,27 +6,6 @@ C90/C99/C++ Comparisons: http://david.tribble.com/text/cdiffs.htm //===---------------------------------------------------------------------===// -Extensions: - - * "#define_target X Y" - This preprocessor directive works exactly the same was as #define, but it - notes that 'X' is a target-specific preprocessor directive. When used, a - diagnostic is emitted indicating that the translation unit is non-portable. - - If a target-define is #undef'd before use, no diagnostic is emitted. If 'X' - were previously a normal #define macro, the macro is tainted. If 'X' is - subsequently #defined as a non-target-specific define, the taint bit is - cleared. - - * "#define_other_target X" - The preprocessor directive takes a single identifier argument. It notes - that this identifier is a target-specific #define for some target other than - the current one. Use of this identifier will result in a diagnostic. - - If 'X' is later #undef'd or #define'd, the taint bit is cleared. If 'X' is - already defined, X is marked as a target-specific define. - -//===---------------------------------------------------------------------===// To time GCC preprocessing speed without output, use: "time gcc -MM file" @@ -159,102 +138,3 @@ The "selection of target" behavior is defined as follows: ppc64-apple-darwin9 (secondary target) The secondary targets are used in the 'portability' model (see below). - -//===---------------------------------------------------------------------===// - -The 'portability' model in clang is sufficient to catch translation units (or -their parts) that are not portable, but it doesn't help if the system headers -are non-portable and not fixed. An alternative model that would be easy to use -is a 'tainting' scheme. Consider: - -int32_t -OSHostByteOrder(void) { -#if defined(__LITTLE_ENDIAN__) - return OSLittleEndian; -#elif defined(__BIG_ENDIAN__) - return OSBigEndian; -#else - return OSUnknownByteOrder; -#endif -} - -It would be trivial to mark 'OSHostByteOrder' as being non-portable (tainted) -instead of marking the entire translation unit. Then, if OSHostByteOrder is -never called/used by the current translation unit, the t-u wouldn't be marked -non-portable. However, there is no good way to handle stuff like: - -extern int X, Y; - -#ifndef __POWERPC__ -#define X Y -#endif - -int bar() { return X; } - -When compiling for powerpc, the #define is skipped, so it doesn't know that bar -uses a #define that is set on some other target. In practice, limited cases -could be handled by scanning the skipped region of a #if, but the fully general -case cannot be implemented efficiently. In this case, for example, the #define -in the protected region could be turned into either a #define_target or -#define_other_target as appropriate. The harder case is code like this (from -OSByteOrder.h): - - #if (defined(__ppc__) || defined(__ppc64__)) - #include <libkern/ppc/OSByteOrder.h> - #elif (defined(__i386__) || defined(__x86_64__)) - #include <libkern/i386/OSByteOrder.h> - #else - #include <libkern/machine/OSByteOrder.h> - #endif - -The realistic way to fix this is by having an initial #ifdef __llvm__ that -defines its contents in terms of the llvm bswap intrinsics. Other things should -be handled on a case-by-case basis. - - -We probably have to do something smarter like this in the future. The C++ header -<limits> contains a lot of code like this: - - static const int digits10 = __LDBL_DIG__; - static const int min_exponent = __LDBL_MIN_EXP__; - static const int min_exponent10 = __LDBL_MIN_10_EXP__; - static const float_denorm_style has_denorm - = bool(__LDBL_DENORM_MIN__) ? denorm_present : denorm_absent; - - ... since this isn't being used in an #ifdef, it should be easy enough to taint -the decl for these ivars. - - -/usr/include/sys/cdefs.h contains stuff like this: - -#if defined(__ppc__) -# if defined(__LDBL_MANT_DIG__) && defined(__DBL_MANT_DIG__) && \ - __LDBL_MANT_DIG__ > __DBL_MANT_DIG__ -# if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__-0 < 1040 -# define __DARWIN_LDBL_COMPAT(x) __asm("_" __STRING(x) "$LDBLStub") -# else -# define __DARWIN_LDBL_COMPAT(x) __asm("_" __STRING(x) "$LDBL128") -# endif -# define __DARWIN_LDBL_COMPAT2(x) __asm("_" __STRING(x) "$LDBL128") -# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 0 -# else -# define __DARWIN_LDBL_COMPAT(x) /* nothing */ -# define __DARWIN_LDBL_COMPAT2(x) /* nothing */ -# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 1 -# endif -#elif defined(__i386__) || defined(__ppc64__) || defined(__x86_64__) -# define __DARWIN_LDBL_COMPAT(x) /* nothing */ -# define __DARWIN_LDBL_COMPAT2(x) /* nothing */ -# define __DARWIN_LONG_DOUBLE_IS_DOUBLE 0 -#else -# error Unknown architecture -#endif - -An ideal way to solve this issue is to mark __DARWIN_LDBL_COMPAT / -__DARWIN_LDBL_COMPAT2 / __DARWIN_LONG_DOUBLE_IS_DOUBLE as being non-portable -because they depend on non-portable macros. In practice though, this may end -up being a serious problem: every use of printf will mark the translation unit -non-portable if targetting ppc32 and something else. - -//===---------------------------------------------------------------------===// - diff --git a/Sema/SemaDecl.cpp b/Sema/SemaDecl.cpp index 3b63a80566..b45317ac9c 100644 --- a/Sema/SemaDecl.cpp +++ b/Sema/SemaDecl.cpp @@ -135,15 +135,6 @@ ScopedDecl *Sema::LookupScopedDecl(IdentifierInfo *II, unsigned NSI, // corresponds to a compiler builtin, create the decl object for the builtin // now, injecting it into translation unit scope, and return it. if (NS == Decl::IDNS_Ordinary) { - // If this is a builtin on some other target, or if this builtin varies - // across targets (e.g. in type), emit a diagnostic and mark the translation - // unit non-portable for using it. - if (II->isNonPortableBuiltin()) { - // Only emit this diagnostic once for this builtin. - II->setNonPortableBuiltin(false); - Context.Target.DiagnoseNonPortability(Context.getFullLoc(IdLoc), - diag::port_target_builtin_use); - } // If this is a builtin on this (or all) targets, create the decl. if (unsigned BuiltinID = II->getBuiltinID()) return LazilyCreateBuiltin(II, BuiltinID, S); diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def index bfc5aca031..97310a1f0b 100644 --- a/include/clang/Basic/DiagnosticKinds.def +++ b/include/clang/Basic/DiagnosticKinds.def @@ -20,19 +20,6 @@ // ERROR - Error, compilation will stop after parsing completes. //===----------------------------------------------------------------------===// -// Portability -//===----------------------------------------------------------------------===// - -DIAG(port_target_macro_use, NOTE, - "use of a target-specific macro, source is not 'portable'") - -DIAG(port_target_builtin_use, NOTE, - "use of a target-specific builtin function, source is not 'portable'") - -DIAG(port_wchar_t, NOTE, - "sizeof(wchar_t) varies between targets, source is not 'portable'") - -//===----------------------------------------------------------------------===// // Lexer Diagnostics //===----------------------------------------------------------------------===// diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index fa3143f656..f64fd6fda4 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -45,10 +45,8 @@ class IdentifierInfo { bool HasMacro : 1; // True if there is a #define for this. bool IsExtension : 1; // True if identifier is a lang extension. bool IsPoisoned : 1; // True if identifier is poisoned. - bool IsOtherTargetMacro : 1; // True if ident is macro on another target. bool IsCPPOperatorKeyword : 1; // True if ident is a C++ operator keyword. - bool IsNonPortableBuiltin : 1; // True if builtin varies across targets. - // 4 bits left in 32-bit word. + // 6 bits left in 32-bit word. void *FETokenInfo; // Managed by the language front-end. IdentifierInfo(const IdentifierInfo&); // NONCOPYABLE. void operator=(const IdentifierInfo&); // NONASSIGNABLE. @@ -106,13 +104,6 @@ public: assert(BuiltinID == ID && "ID too large for field!"); } - /// isNonPortableBuiltin - Return true if this identifier corresponds to a - /// builtin on some other target, but isn't one on this target, or if it is on - /// the target but not on another, or if it is on both but it differs somehow - /// in behavior. - bool isNonPortableBuiltin() const { return IsNonPortableBuiltin; } - void setNonPortableBuiltin(bool Val) { IsNonPortableBuiltin = Val; } - /// get/setExtension - Initialize information about whether or not this /// language token is an extension. This controls extension warnings, and is /// only valid if a custom token ID is set. @@ -126,11 +117,6 @@ public: /// isPoisoned - Return true if this token has been poisoned. bool isPoisoned() const { return IsPoisoned; } - /// setIsOtherTargetMacro/isOtherTargetMacro control whether this identifier - /// is seen as being a macro on some other target. - void setIsOtherTargetMacro(bool Val = true) { IsOtherTargetMacro = Val; } - bool isOtherTargetMacro() const { return IsOtherTargetMacro; } - /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether /// this identifier is a C++ alternate representation of an operator. void setIsCPlusPlusOperatorKeyword(bool Val = true) diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 0550e51e82..16c959c6d0 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -29,33 +29,13 @@ class SourceManager; namespace Builtin { struct Info; } -/// TargetInfo - This class exposes information about the current target set. -/// A target set consists of a primary target and zero or more secondary targets -/// which are each represented by a TargetInfoImpl object. TargetInfo responds -/// to various queries as though it were the primary target, but keeps track of, -/// and warns about, the first query made of it that are contradictary among the -/// targets it tracks. For example, if it contains a "PPC32" and "PPC64" -/// target, it will warn the first time the size of the 'long' datatype is -/// queried. +/// TargetInfo - This class exposes information about the current target. /// class TargetInfo { /// Primary - This tracks the primary target in the target set. /// - const TargetInfoImpl *PrimaryTarget; + const TargetInfoImpl *Target; - /// SecondaryTargets - This tracks the set of secondary targets. - /// - std::vector<const TargetInfoImpl*> SecondaryTargets; - - /// Diag - If non-null, this object is used to report the first use of - /// non-portable functionality in the translation unit. - /// - Diagnostic *Diag; - - /// NonPortable - This instance variable keeps track of whether or not the - /// current translation unit is portable across the set of targets tracked. - bool NonPortable; - /// These are all caches for target values. unsigned WCharWidth, WCharAlign; @@ -63,53 +43,22 @@ class TargetInfo { // TargetInfo Construction. //==----------------------------------------------------------------==/ - TargetInfo(const TargetInfoImpl *Primary, Diagnostic *D = 0) { - PrimaryTarget = Primary; - Diag = D; - NonPortable = false; + TargetInfo(const TargetInfoImpl *TII) { + Target = TII; // Initialize Cache values to uncomputed. WCharWidth = 0; } - /// AddSecondaryTarget - Add a secondary target to the target set. - void AddSecondaryTarget(const TargetInfoImpl *Secondary) { - SecondaryTargets.push_back(Secondary); - } - public: - /// CreateTargetInfo - Create a TargetInfo object from a group of - /// target triples. The first target triple is considered the primary - /// target. - static TargetInfo* CreateTargetInfo(const std::string* TriplesBeg, - const std::string* TripledEnd, - Diagnostic* Diags = NULL); + /// CreateTargetInfo - Return the target info object for the specified target + /// triple. + static TargetInfo* CreateTargetInfo(const std::string &Triple); ~TargetInfo(); - //==----------------------------------------------------------------==/ - // Accessors. - //==----------------------------------------------------------------==/ - - /// isNonPortable - Return true if the current translation unit has used a - /// target property that is non-portable across the secondary targets. - bool isNonPortable() const { - return NonPortable; - } - - /// isPortable - Return true if this translation unit is portable across the - /// secondary targets so far. - bool isPortable() const { - return !NonPortable; - } - ///===---- Target property query methods --------------------------------===// - /// DiagnoseNonPortability - Emit a diagnostic indicating that the current - /// translation unit is non-portable due to a construct at the specified - /// location. DiagKind indicates what went wrong. - void DiagnoseNonPortability(FullSourceLoc Loc, unsigned DiagKind); - /// getTargetDefines - Appends the target-specific #define values for this /// target set to the specified buffer. void getTargetDefines(std::vector<char> &DefineBuffer); @@ -197,8 +146,8 @@ public: /// getTargetBuiltins - Return information about target-specific builtins for /// the current primary target, and info about which builtins are non-portable /// across the current set of primary and secondary targets. - void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords, - std::vector<const char *> &NonPortableBuiltins) const; + void getTargetBuiltins(const Builtin::Info *&Records, + unsigned &NumRecords) const; /// getVAListDeclaration - Return the declaration to use for /// __builtin_va_list, which is target-specific. diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index d4c9265146..9b636183dd 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -79,11 +79,6 @@ PPKEYWORD(sccs) PPKEYWORD(assert) PPKEYWORD(unassert) -// clang extensions. -PPKEYWORD(define_target) -PPKEYWORD(define_other_target) - - //===----------------------------------------------------------------------===// // Language keywords. //===----------------------------------------------------------------------===// diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index f690d955bd..c63b701a85 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -59,9 +59,6 @@ class MacroInfo { /// it has not yet been redefined or undefined. bool IsBuiltinMacro : 1; - /// IsTargetSpecific - True if this is a target-specific macro defined with - /// #define_target. - bool IsTargetSpecific : 1; private: //===--------------------------------------------------------------------===// // State that changes as the macro is used. @@ -97,13 +94,6 @@ public: IsBuiltinMacro = Val; } - /// setIsTargetSpecific - Set or clear the IsTargetSpecific flag. - /// - void setIsTargetSpecific(bool Val = true) { - IsTargetSpecific = Val; - } - bool isTargetSpecific() const { return IsTargetSpecific; } - /// setIsUsed - Set the value of the IsUsed flag. /// void setIsUsed(bool Val) { diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 1a8c2937ec..e18b40ac56 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -480,9 +480,8 @@ private: void HandleImportDirective(Token &Tok); // Macro handling. - void HandleDefineDirective(Token &Tok, bool isTargetSpecific); + void HandleDefineDirective(Token &Tok); void HandleUndefDirective(Token &Tok); - void HandleDefineOtherTargetDirective(Token &Tok); // HandleAssertDirective(Token &Tok); // HandleUnassertDirective(Token &Tok); diff --git a/test/Parser/portability.c b/test/Parser/portability.c deleted file mode 100644 index b6e9715285..0000000000 --- a/test/Parser/portability.c +++ /dev/null @@ -1,5 +0,0 @@ -// RUN: clang -arch ppc -arch bogusW16W16 -fsyntax-only %s 2>&1 | grep note | wc -l | grep 1 - -// wchar_t varies across targets. -void *X = L"foo"; - |