r198897 - __has_attribute now understands target-specific attributes. So when you ask whether an ARM target has the "interrupt" attribute, it will return true for ARM and MSP430 targets, and false for others.

Aaron Ballman aaron at aaronballman.com
Thu Jan 9 14:57:44 PST 2014


Author: aaronballman
Date: Thu Jan  9 16:57:44 2014
New Revision: 198897

URL: http://llvm.org/viewvc/llvm-project?rev=198897&view=rev
Log:
__has_attribute now understands target-specific attributes. So when you ask whether an ARM target has the "interrupt" attribute, it will return true for ARM and MSP430 targets, and false for others.

Modified:
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp
    cfe/trunk/test/Preprocessor/has_attribute.c
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=198897&r1=198896&r2=198897&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Thu Jan  9 16:57:44 2014
@@ -1045,7 +1045,7 @@ static bool HasExtension(const Preproces
 
 /// HasAttribute -  Return true if we recognize and implement the attribute
 /// specified by the given identifier.
-static bool HasAttribute(const IdentifierInfo *II) {
+static bool HasAttribute(const IdentifierInfo *II, const llvm::Triple &T) {
   StringRef Name = II->getName();
   // Normalize the attribute name, __foo__ becomes foo.
   if (Name.size() >= 4 && Name.startswith("__") && Name.endswith("__"))
@@ -1395,7 +1395,7 @@ void Preprocessor::ExpandBuiltinMacro(To
       // Check for a builtin is trivial.
       Value = FeatureII->getBuiltinID() != 0;
     } else if (II == Ident__has_attribute)
-      Value = HasAttribute(FeatureII);
+      Value = HasAttribute(FeatureII, getTargetInfo().getTriple());
     else if (II == Ident__has_extension)
       Value = HasExtension(*this, FeatureII);
     else {

Modified: cfe/trunk/test/Preprocessor/has_attribute.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/has_attribute.c?rev=198897&r1=198896&r2=198897&view=diff
==============================================================================
--- cfe/trunk/test/Preprocessor/has_attribute.c (original)
+++ cfe/trunk/test/Preprocessor/has_attribute.c Thu Jan  9 16:57:44 2014
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -E %s -o - | FileCheck %s
+// RUN: %clang_cc1 -triple arm-unknown-linux -E %s -o - | FileCheck %s
 
 // CHECK: always_inline
 #if __has_attribute(always_inline)
@@ -38,3 +38,13 @@ int has_something_we_dont_have();
 #if !__has_attribute(volatile)
 int has_no_volatile_attribute();
 #endif
+
+// CHECK: has_arm_interrupt
+#if __has_attribute(interrupt)
+  int has_arm_interrupt();
+#endif
+
+// CHECK: does_not_have_dllexport
+#if !__has_attribute(dllexport)
+  int does_not_have_dllexport();
+#endif

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=198897&r1=198896&r2=198897&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Thu Jan  9 16:57:44 2014
@@ -1537,18 +1537,55 @@ void EmitClangAttrPCHWrite(RecordKeeper
 
 // Emits the list of spellings for attributes.
 void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
-  emitSourceFileHeader("llvm::StringSwitch code to match all known attributes",
-                       OS);
+  emitSourceFileHeader("llvm::StringSwitch code to match attributes based on "
+                       "the target triple, T", OS);
 
   std::vector<Record*> Attrs = Records.getAllDerivedDefinitions("Attr");
   
-  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end(); I != E; ++I) {
+  for (std::vector<Record*>::iterator I = Attrs.begin(), E = Attrs.end();
+       I != E; ++I) {
     Record &Attr = **I;
 
-    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
+    // It is assumed that there will be an llvm::Triple object named T within
+    // scope that can be used to determine whether the attribute exists in
+    // a given target.
+    std::string Test;
+    if (Attr.isSubClassOf("TargetSpecificAttr")) {
+      const Record *R = Attr.getValueAsDef("Target");
+      std::vector<std::string> Arches = R->getValueAsListOfStrings("Arches");
+
+      Test += "(";
+      for (std::vector<std::string>::const_iterator AI = Arches.begin(),
+           AE = Arches.end(); AI != AE; ++AI) {
+        std::string Part = *AI;
+        Test += "T.getArch() == llvm::Triple::" + Part;
+        if (AI + 1 != AE)
+          Test += " || ";
+      }
+      Test += ")";
+
+      std::vector<std::string> OSes;
+      if (!R->isValueUnset("OSes")) {
+        Test += " && (";
+        std::vector<std::string> OSes = R->getValueAsListOfStrings("OSes");
+        for (std::vector<std::string>::const_iterator AI = OSes.begin(),
+             AE = OSes.end(); AI != AE; ++AI) {
+          std::string Part = *AI;
 
-    for (std::vector<Record*>::const_iterator I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
-      OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", true)\n";
+          Test += "T.getOS() == llvm::Triple::" + Part;
+          if (AI + 1 != AE)
+            Test += " || ";
+        }
+        Test += ")";
+      }
+    } else
+      Test = "true";
+
+    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
+    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
+         E = Spellings.end(); I != E; ++I) {
+      OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " << Test;
+      OS << ")\n";
     }
   }
 





More information about the cfe-commits mailing list