]> granicus.if.org Git - clang/commitdiff
Teach the diagnostics engine about the Attr type to make reporting on semantic attrib...
authorAaron Ballman <aaron@aaronballman.com>
Thu, 26 Dec 2013 18:30:57 +0000 (18:30 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Thu, 26 Dec 2013 18:30:57 +0000 (18:30 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@198055 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Attr.h
include/clang/Basic/Diagnostic.h
include/clang/Basic/DiagnosticSemaKinds.td
lib/AST/ASTDiagnostic.cpp
lib/Basic/Diagnostic.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclAttr.cpp
test/Rewriter/missing-dllimport.c
test/Sema/dllimport-dllexport.c
test/SemaCXX/MicrosoftExtensions.cpp
utils/TableGen/ClangAttrEmitter.cpp

index d5dc537baf298b79c26be8b006ca61a02a35536c..61130b5dc12ee4b1650f05d8ef6018b2a08ec1f4 100644 (file)
@@ -85,6 +85,7 @@ public:
   }
   
   unsigned getSpellingListIndex() const { return SpellingListIndex; }
+  virtual const char *getSpelling() const = 0;
 
   SourceLocation getLocation() const { return Range.getBegin(); }
   SourceRange getRange() const { return Range; }
@@ -138,6 +139,19 @@ public:
 
 #include "clang/AST/Attrs.inc"
 
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+                                           const Attr *At) {
+  DB.AddTaggedVal(reinterpret_cast<intptr_t>(At),
+                  DiagnosticsEngine::ak_attr);
+  return DB;
+}
+
+inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD,
+                                           const Attr *At) {
+  PD.AddTaggedVal(reinterpret_cast<intptr_t>(At),
+                  DiagnosticsEngine::ak_attr);
+  return PD;
+}
 }  // end namespace clang
 
 #endif
index 2b0b3f9b28ca0f3d36cddc8a57fef71f2d4bdb9c..97f2e80244c4601352b6cdbd6129424c345e5286 100644 (file)
@@ -166,7 +166,8 @@ public:
     ak_nameddecl,       ///< NamedDecl *
     ak_nestednamespec,  ///< NestedNameSpecifier *
     ak_declcontext,     ///< DeclContext *
-    ak_qualtype_pair    ///< pair<QualType, QualType>
+    ak_qualtype_pair,   ///< pair<QualType, QualType>
+    ak_attr             ///< Attr *
   };
 
   /// \brief Represents on argument value, which is a union discriminated
index 54a4159ee6de40a0549e9d5a337fc20457f10405..c3ac6fbd78e318b4e9e74957dcb6966a144824be 100644 (file)
@@ -6722,7 +6722,7 @@ def err_opencl_global_invalid_addr_space : Error<
   "global variables must have a constant address space qualifier">;
 def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
 def err_opencl_kernel_attr :
-  Error<"attribute '%0' can only be applied to a kernel function">;
+  Error<"attribute %0 can only be applied to a kernel function">;
 } // end of sema category
 
 let CategoryName = "OpenMP Issue" in {
index 7f7221fc6ed1371b8a2c76f1202c5a0e3c049c63..f3c2b224e1df98154e45592526c3b0803965cfd0 100644 (file)
@@ -12,6 +12,7 @@
 //===----------------------------------------------------------------------===//
 #include "clang/AST/ASTDiagnostic.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/Attr.h"
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
@@ -359,6 +360,14 @@ void clang::FormatASTNodeDiagnosticArgument(
       NeedQuotes = false;
       break;
     }
+    case DiagnosticsEngine::ak_attr: {\r
+      const Attr *At = reinterpret_cast<Attr *>(Val);\r
+      assert(At && "Received null Attr object!");\r
+      OS << '\'' << At->getSpelling() << '\'';\r
+      NeedQuotes = false;\r
+      break;\r
+    }\r
+
   }
 
   OS.flush();
index 4a6f070af70367293809cc09f7d9a86413939f02..eaae388fd8d54d07fdb27da6e585e64864ca810f 100644 (file)
@@ -861,6 +861,7 @@ FormatDiagnostic(const char *DiagStr, const char *DiagEnd,
     case DiagnosticsEngine::ak_nameddecl:
     case DiagnosticsEngine::ak_nestednamespec:
     case DiagnosticsEngine::ak_declcontext:
+    case DiagnosticsEngine::ak_attr:
       getDiags()->ConvertArgToString(Kind, getRawArg(ArgNo),
                                      Modifier, ModifierLen,
                                      Argument, ArgumentLen,
index 9ed9510a65936b05ecb8abd9398d94494e7012a8..fd576f3d5addc739a94c3d2fa2c9b27bc117f942 100644 (file)
@@ -8934,7 +8934,7 @@ Sema::FinalizeDeclaration(Decl *ThisDecl) {
 
   if (UsedAttr *Attr = VD->getAttr<UsedAttr>()) {
     if (!Attr->isInherited() && !VD->isThisDeclarationADefinition()) {
-      Diag(Attr->getLocation(), diag::warn_attribute_ignored) << "'used'";
+      Diag(Attr->getLocation(), diag::warn_attribute_ignored) << Attr;
       VD->dropAttr<UsedAttr>();
     }
   }
@@ -9674,7 +9674,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
         !(LangOpts.MicrosoftExt && FD->getLexicalDeclContext()->isRecord())) {
       Diag(FD->getLocation(),
            diag::err_attribute_can_be_applied_only_to_symbol_declaration)
-        << "dllimport";
+        << DA;
       FD->setInvalidDecl();
       return D;
     }
@@ -9687,7 +9687,7 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) {
       // emitted.
       Diag(FD->getLocation(),
            diag::warn_redeclaration_without_attribute_prev_attribute_ignored)
-        << FD->getName() << "dllimport";
+        << FD->getName() << DA;
     }
   }
   // We want to attach documentation to original Decl (which might be
index 26988b2326873acbf4fff2729d086e4bd8cad644..56e8725ab6ff353c650f69a7778a4d183d3da6d2 100644 (file)
@@ -1557,8 +1557,8 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
     return result; // This will be returned in a register
   }
 */
-  if (D->hasAttr<VecReturnAttr>()) {
-    S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
+  if (VecReturnAttr *A = D->getAttr<VecReturnAttr>()) {
+    S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << A;
     return;
   }
 
@@ -4127,18 +4127,16 @@ void Sema::ProcessDeclAttributeList(Scope *S, Decl *D,
 
   if (!D->hasAttr<OpenCLKernelAttr>()) {
     // These attributes cannot be applied to a non-kernel function.
-    if (D->hasAttr<ReqdWorkGroupSizeAttr>()) {
-      Diag(D->getLocation(), diag::err_opencl_kernel_attr)
-          << "reqd_work_group_size";
+    if (Attr *A = D->getAttr<ReqdWorkGroupSizeAttr>()) {
+      Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
       D->setInvalidDecl();
     }
-    if (D->hasAttr<WorkGroupSizeHintAttr>()) {
-      Diag(D->getLocation(), diag::err_opencl_kernel_attr)
-          << "work_group_size_hint";
+    if (Attr *A = D->getAttr<WorkGroupSizeHintAttr>()) {
+      Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
       D->setInvalidDecl();
     }
-    if (D->hasAttr<VecTypeHintAttr>()) {
-      Diag(D->getLocation(), diag::err_opencl_kernel_attr) << "vec_type_hint";
+    if (Attr *A = D->getAttr<VecTypeHintAttr>()) {
+      Diag(D->getLocation(), diag::err_opencl_kernel_attr) << A;
       D->setInvalidDecl();
     }
   }
index 127989b0ed8a332bbbaffd521e687fb3609531fa..1e4689fba0db33c9c548a66ef1ace60f3fae1786 100644 (file)
@@ -13,7 +13,7 @@ void bar() { return 1; }
 
 // CHECK-NEG: error: void function 'bar' should not return a value
 // CHECK-NEG: 1 error generated
-// CHECK-POS: warning: 'foo' redeclared without dllimport attribute: previous dllimport ignored
+// CHECK-POS: warning: 'foo' redeclared without 'dllimport' attribute: previous 'dllimport' ignored
 // CHECK-POS: error: void function 'bar' should not return a value
 // CHECK-POS: 1 warning and 1 error generated
 
index 198c25f90caa1c5455dd17db3ad8c685a47a69be..e93507846e60954913319b1ed4ad615b11c2f945 100644 (file)
@@ -4,7 +4,7 @@
 inline void __attribute__((dllexport)) foo1(){} // expected-warning{{'dllexport' attribute ignored}}
 inline void __attribute__((dllimport)) foo2(){} // expected-warning{{'dllimport' attribute ignored}}
 
-void __attribute__((dllimport)) foo3(){} // expected-error{{dllimport attribute can be applied only to symbol declaration}}
+void __attribute__((dllimport)) foo3(){} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
 
 void __attribute__((dllimport, dllexport)) foo4(); // expected-warning{{dllimport attribute ignored}}
 
@@ -16,13 +16,13 @@ typedef int __attribute__((dllexport)) type6; // expected-warning{{'dllexport' a
 typedef int __attribute__((dllimport)) type7; // expected-warning{{'dllimport' attribute only applies to variables and functions}}
 
 void __attribute__((dllimport)) foo6();
-void foo6(){} // expected-warning {{'foo6' redeclared without dllimport attribute: previous dllimport ignored}}
+void foo6(){} // expected-warning {{'foo6' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 
 // PR6269
 inline void __declspec(dllexport) foo7(){} // expected-warning{{'dllexport' attribute ignored}}
 inline void __declspec(dllimport) foo8(){} // expected-warning{{'dllimport' attribute ignored}}
 
-void __declspec(dllimport) foo9(){} // expected-error{{dllimport attribute can be applied only to symbol declaration}}
+void __declspec(dllimport) foo9(){} // expected-error{{'dllimport' attribute can be applied only to symbol declaration}}
 
 void __declspec(dllimport) __declspec(dllexport) foo10(); // expected-warning{{dllimport attribute ignored}}
 
@@ -34,7 +34,7 @@ typedef int __declspec(dllexport) type1; // expected-warning{{'dllexport' attrib
 typedef int __declspec(dllimport) type2; // expected-warning{{'dllimport' attribute only applies to variables and functions}}
 
 void __declspec(dllimport) foo12();
-void foo12(){} // expected-warning {{'foo12' redeclared without dllimport attribute: previous dllimport ignored}}
+void foo12(){} // expected-warning {{'foo12' redeclared without 'dllimport' attribute: previous 'dllimport' ignored}}
 
 void __attribute__((dllimport)) foo13(); // expected-warning{{dllimport attribute ignored}}
 void __attribute__((dllexport)) foo13();
index 5c51331500b5352d4980bac1f72571810f926c5b..32b8adb5df3f69d2eb5e1b99a37f40087a47301d 100644 (file)
@@ -37,11 +37,11 @@ class B : public A {
 // MSVC allows type definition in anonymous union and struct
 struct A
 {
-  union 
+  union
   {
     int a;
     struct B  // expected-warning {{types declared in an anonymous union are a Microsoft extension}}
-    { 
+    {
       int c;
     } d;
 
@@ -63,7 +63,7 @@ struct A
     {
       int c2;
     } d2;
-    
+
        union C2  // expected-warning {{types declared in an anonymous struct are a Microsoft extension}}
     {
       int e2;
@@ -78,7 +78,7 @@ struct A
 // __stdcall handling
 struct M {
     int __stdcall addP();
-    float __stdcall subtractP(); 
+    float __stdcall subtractP();
 };
 
 // __unaligned handling
@@ -90,7 +90,7 @@ template<typename T> void h1(T (__stdcall M::* const )()) { }
 void m1() {
   h1<int>(&M::addP);
   h1(&M::subtractP);
-} 
+}
 
 
 
@@ -98,7 +98,7 @@ void m1() {
 
 void f(long long);
 void f(int);
+
 int main()
 {
   // This is an ambiguous call in standard C++.
@@ -126,7 +126,7 @@ __declspec(dllimport) void f(void) { }
 void f2(void);
 };
 
-__declspec(dllimport) void AAA::f2(void) { // expected-error {{dllimport attribute can be applied only to symbol}}
+__declspec(dllimport) void AAA::f2(void) { // expected-error {{'dllimport' attribute can be applied only to symbol}}
 
 }
 
@@ -368,18 +368,18 @@ struct StructWithUnnamedMember {
 
 namespace rdar14250378 {
   class Bar {};
-  
+
   namespace NyNamespace {
     class Foo {
     public:
       Bar* EnsureBar();
     };
-    
+
     class Baz : public Foo {
     public:
       friend class Bar;
     };
-    
+
     Bar* Foo::EnsureBar() {
       return 0;
     }
index d32f3a61e88484c64a19cfe0c8a41cb9689a3894..ef753946da49d0f61ef07f2a15a058d3b8d861e4 100644 (file)
@@ -954,6 +954,29 @@ static void writeAvailabilityValue(raw_ostream &OS) {
      << "  OS << \"";
 }
 
+static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
+  std::vector<Record *> Spellings = R.getValueAsListOfDefs("Spellings");
+
+  OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
+  if (Spellings.empty()) {
+    OS << "  return \"(No spelling)\";\n}\n\n";
+    return;
+  }
+
+  OS << "  switch (SpellingListIndex) {\n"
+        "  default:\n"
+        "    llvm_unreachable(\"Unknown attribute spelling!\");\n"
+        "    return \"(No spelling)\";\n";
+
+  for (unsigned I = 0; I < Spellings.size(); ++I)
+    OS << "  case " << I << ":\n"
+          "    return \"" << Spellings[I]->getValueAsString("Name") << "\";\n";
+  // End of the switch statement.
+  OS << "  }\n";
+  // End of the getSpelling function.
+  OS << "}\n\n";
+}
+
 static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
                                      raw_ostream &OS) {
   std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
@@ -1197,6 +1220,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
     OS << "  virtual " << R.getName() << "Attr *clone (ASTContext &C) const;\n";
     OS << "  virtual void printPretty(raw_ostream &OS,\n"
        << "                           const PrintingPolicy &Policy) const;\n";
+    OS << "  virtual const char *getSpelling() const;\n";
 
     writeAttrAccessorDefinition(R, OS);
 
@@ -1328,6 +1352,7 @@ void EmitClangAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
     OS << ", getSpellingListIndex());\n}\n\n";
 
     writePrettyPrintFunction(R, Args, OS);
+    writeGetSpellingFunction(R, OS);
   }
 }