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";
     }
   }
 


_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to