[cfe-commits] r59907 - in /cfe/trunk: include/clang/AST/Type.h include/clang/Analysis/PathSensitive/BugReporter.h include/clang/Basic/Diagnostic.h include/clang/Basic/DiagnosticKinds.def lib/Basic/Diagnostic.cpp lib/Sema/Sema.cpp lib/Sema/SemaExpr.cpp

Chris Lattner sabre at nondot.org
Sun Nov 23 01:13:31 PST 2008


Author: lattner
Date: Sun Nov 23 03:13:29 2008
New Revision: 59907

URL: http://llvm.org/viewvc/llvm-project?rev=59907&view=rev
Log:
Add support for sending QualType's directly into diags and convert two
diags over to use this.  QualTypes implicitly print single quotes around 
them for uniformity and future extension.

Doing this requires a little function pointer dance to prevent libbasic
from depending on libast.


Modified:
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Analysis/PathSensitive/BugReporter.h
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def
    cfe/trunk/lib/Basic/Diagnostic.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=59907&r1=59906&r2=59907&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Sun Nov 23 03:13:29 2008
@@ -14,11 +14,11 @@
 #ifndef LLVM_CLANG_AST_TYPE_H
 #define LLVM_CLANG_AST_TYPE_H
 
+#include "clang/Basic/Diagnostic.h"
 #include "llvm/Support/Casting.h"
 #include "llvm/ADT/FoldingSet.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/Bitcode/SerializationFwd.h"
-
 using llvm::isa;
 using llvm::cast;
 using llvm::cast_or_null;
@@ -1486,6 +1486,16 @@
     return false;
 }
 
+/// Insertion operator for diagnostics.  This allows sending QualType's into a
+/// diagnostic with <<.
+inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
+                                           QualType T) {
+  DB.AddTaggedVal(reinterpret_cast<intptr_t>(T.getAsOpaquePtr()),
+                  Diagnostic::ak_qualtype);
+  return DB;
+}
+  
+
 }  // end namespace clang
 
 #endif

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/BugReporter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/BugReporter.h?rev=59907&r1=59906&r2=59907&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/BugReporter.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/BugReporter.h Sun Nov 23 03:13:29 2008
@@ -21,6 +21,7 @@
 #include "clang/Analysis/PathSensitive/ExplodedGraph.h"
 #include "llvm/ADT/SmallPtrSet.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/StringExtras.h"
 #include <list>
 
@@ -316,6 +317,7 @@
     for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
       R.addRange(Info.getRange(i));
     
+    // FIXME: This is losing/ignoring formatting.
     for (unsigned i = 0, e = Info.getNumArgs(); i != e; ++i) {
       switch (Info.getArgKind(i)) {
       case Diagnostic::ak_std_string:   
@@ -333,7 +335,13 @@
       case Diagnostic::ak_identifierinfo:
         R.addString(Info.getArgIdentifier(i)->getName());
         break;
-          
+      case Diagnostic::ak_qualtype: {
+        llvm::SmallString<64> Str;
+        Info.getDiags()->ConvertQualTypeToString(Info.getRawArg(i), 0, 0, 0, 0,
+                                                 Str);
+        R.addString(std::string(Str.begin(), Str.end()));
+        break;
+      }
       }
     }
   }

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=59907&r1=59906&r2=59907&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Sun Nov 23 03:13:29 2008
@@ -84,6 +84,12 @@
   /// CustomDiagInfo - Information for uniquing and looking up custom diags.
   diag::CustomDiagInfo *CustomDiagInfo;
 
+  /// QualTypeToString - A function pointer that converts QualType's to strings.
+  /// This is a hack to avoid a layering violation between libbasic and libsema.
+  typedef void (*QTToStringFnTy)(intptr_t QT, const char *Modifier, unsigned ML,
+                                 const char *Argument, unsigned ArgLen,
+                                 llvm::SmallVectorImpl<char> &Output);
+  QTToStringFnTy QualTypeToString;
 public:
   explicit Diagnostic(DiagnosticClient *client = 0);
   ~Diagnostic();
@@ -150,6 +156,19 @@
   /// registered and created, otherwise the existing ID is returned.
   unsigned getCustomDiagID(Level L, const char *Message);
   
+  
+  /// ConvertQualTypeToString - This method converts a QualType (as an intptr_t)
+  /// into the string that represents it if possible.
+  void ConvertQualTypeToString(intptr_t QT, const char *Modifier, unsigned ML,
+                               const char *Argument, unsigned ArgLen,
+                               llvm::SmallVectorImpl<char> &Output) const {
+    QualTypeToString(QT, Modifier, ML, Argument, ArgLen, Output);
+  }
+  
+  void SetQualTypeToStringFn(QTToStringFnTy Fn) {
+    QualTypeToString = Fn;
+  }
+  
   //===--------------------------------------------------------------------===//
   // Diagnostic classification and reporting interfaces.
   //
@@ -233,7 +252,8 @@
     ak_c_string,       // const char *
     ak_sint,           // int
     ak_uint,           // unsigned
-    ak_identifierinfo  // IdentifierInfo
+    ak_identifierinfo, // IdentifierInfo
+    ak_qualtype        // QualType
   };
 };
 
@@ -273,11 +293,14 @@
   ~DiagnosticBuilder() {
     // If DiagObj is null, then its soul was stolen by the copy ctor.
     if (DiagObj == 0) return;
-    
-    
+
+    // When destroyed, the ~DiagnosticBuilder sets the final argument count into
+    // the Diagnostic object.
     DiagObj->NumDiagArgs = NumArgs;
     DiagObj->NumDiagRanges = NumRanges;
 
+    // Process the diagnostic, sending the accumulated information to the
+    // DiagnosticClient.
     DiagObj->ProcessDiag();
 
     // This diagnostic is no longer in flight.
@@ -419,6 +442,14 @@
     return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]);
   }
   
+  /// getRawArg - Return the specified non-string argument in an opaque form.
+  intptr_t getRawArg(unsigned Idx) const {
+    assert(getArgKind(Idx) != Diagnostic::ak_std_string &&
+           "invalid argument accessor!");
+    return DiagObj->DiagArgumentsVal[Idx];
+  }
+  
+  
   /// getNumRanges - Return the number of source ranges associated with this
   /// diagnostic.
   unsigned getNumRanges() const {

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=59907&r1=59906&r2=59907&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sun Nov 23 03:13:29 2008
@@ -1123,9 +1123,9 @@
 DIAG(err_typecheck_unary_expr, ERROR,
      "invalid argument type to unary expression '%0'")
 DIAG(err_typecheck_indirection_requires_pointer, ERROR,
-     "indirection requires pointer operand ('%0' invalid)")
+     "indirection requires pointer operand (%0 invalid)")
 DIAG(err_typecheck_invalid_operands, ERROR,
-     "invalid operands to binary expression ('%0' and '%1')")
+     "invalid operands to binary expression (%0 and %1)")
 DIAG(err_typecheck_sub_ptr_object, ERROR,
      "'%0' is not a complete object type")
 DIAG(err_typecheck_sub_ptr_compatible, ERROR,

Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=59907&r1=59906&r2=59907&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Sun Nov 23 03:13:29 2008
@@ -116,6 +116,14 @@
 // Common Diagnostic implementation
 //===----------------------------------------------------------------------===//
 
+static void DummyQTToStringFnTy(intptr_t QT, const char *Modifier, unsigned ML,
+                                const char *Argument, unsigned ArgLen,
+                                llvm::SmallVectorImpl<char> &Output) {
+  const char *Str = "<can't format QualType>";
+  Output.append(Str, Str+strlen(Str));
+}
+
+
 Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
   IgnoreAllWarnings = false;
   WarningsAsErrors = false;
@@ -130,6 +138,8 @@
   NumErrors = 0;
   CustomDiagInfo = 0;
   CurDiagID = ~0U;
+  
+  QualTypeToString = DummyQTToStringFnTy;
 }
 
 Diagnostic::~Diagnostic() {
@@ -468,29 +478,29 @@
     }
       
     assert(isdigit(*DiagStr) && "Invalid format for argument in diagnostic");
-    unsigned StrNo = *DiagStr++ - '0';
+    unsigned ArgNo = *DiagStr++ - '0';
 
-    switch (getArgKind(StrNo)) {
+    switch (getArgKind(ArgNo)) {
     case Diagnostic::ak_std_string: {
-      const std::string &S = getArgStdStr(StrNo);
+      const std::string &S = getArgStdStr(ArgNo);
       assert(ModifierLen == 0 && "No modifiers for strings yet");
       OutStr.append(S.begin(), S.end());
       break;
     }
     case Diagnostic::ak_c_string: {
-      const char *S = getArgCStr(StrNo);
+      const char *S = getArgCStr(ArgNo);
       assert(ModifierLen == 0 && "No modifiers for strings yet");
       OutStr.append(S, S + strlen(S));
       break;
     }
     case Diagnostic::ak_identifierinfo: {
-      const IdentifierInfo *II = getArgIdentifier(StrNo);
+      const IdentifierInfo *II = getArgIdentifier(ArgNo);
       assert(ModifierLen == 0 && "No modifiers for strings yet");
       OutStr.append(II->getName(), II->getName() + II->getLength());
       break;
     }
     case Diagnostic::ak_sint: {
-      int Val = getArgSInt(StrNo);
+      int Val = getArgSInt(ArgNo);
       
       if (ModifierIs(Modifier, ModifierLen, "select")) {
         HandleSelectModifier((unsigned)Val, Argument, ArgumentLen, OutStr);
@@ -507,7 +517,7 @@
       break;
     }
     case Diagnostic::ak_uint: {
-      unsigned Val = getArgUInt(StrNo);
+      unsigned Val = getArgUInt(ArgNo);
       
       if (ModifierIs(Modifier, ModifierLen, "select")) {
         HandleSelectModifier(Val, Argument, ArgumentLen, OutStr);
@@ -521,9 +531,16 @@
         // FIXME: Optimize
         std::string S = llvm::utostr_32(Val);
         OutStr.append(S.begin(), S.end());
-        break;
       }
+      break;
     }
+    case Diagnostic::ak_qualtype:
+      OutStr.push_back('\'');
+      getDiags()->ConvertQualTypeToString(getRawArg(ArgNo),
+                                          Modifier, ModifierLen,
+                                          Argument, ArgumentLen, OutStr);
+      OutStr.push_back('\'');
+      break;
     }
   }
 }

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=59907&r1=59906&r2=59907&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Sun Nov 23 03:13:29 2008
@@ -20,6 +20,22 @@
 #include "clang/Basic/Diagnostic.h"
 using namespace clang;
 
+/// ConvertQualTypeToStringFn - This function is used to pretty print the 
+/// specified QualType as a string in diagnostics.
+static void ConvertQualTypeToStringFn(intptr_t QT,
+                                      const char *Modifier, unsigned ML,
+                                      const char *Argument, unsigned ArgLen,
+                                      llvm::SmallVectorImpl<char> &Output) {
+  assert(ML == 0 && ArgLen == 0 && "Invalid modifier for QualType argument");
+
+  QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(QT)));
+  
+  // FIXME: Playing with std::string is really slow.
+  std::string S = Ty.getAsString();
+  Output.append(S.begin(), S.end());
+}
+
+
 static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
   if (C.getLangOptions().CPlusPlus)
     return CXXRecordDecl::Create(C, TagDecl::TK_struct, 
@@ -108,6 +124,9 @@
   TUScope = 0;
   if (getLangOptions().CPlusPlus)
     FieldCollector.reset(new CXXFieldCollector());
+      
+  // Tell diagnostics how to render things from the AST library.
+  PP.getDiagnostics().SetQualTypeToStringFn(ConvertQualTypeToStringFn);
 }
 
 /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit cast. 

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=59907&r1=59906&r2=59907&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Sun Nov 23 03:13:29 2008
@@ -2054,7 +2054,7 @@
 
 QualType Sema::InvalidOperands(SourceLocation Loc, Expr *&lex, Expr *&rex) {
   Diag(Loc, diag::err_typecheck_invalid_operands)
-    << lex->getType().getAsString() << rex->getType().getAsString()
+    << lex->getType() << rex->getType()
     << lex->getSourceRange() << rex->getSourceRange();
   return QualType();
 }
@@ -2809,20 +2809,19 @@
   return Context.getPointerType(op->getType());
 }
 
-QualType Sema::CheckIndirectionOperand(Expr *op, SourceLocation OpLoc) {
-  UsualUnaryConversions(op);
-  QualType qType = op->getType();
-  
-  if (const PointerType *PT = qType->getAsPointerType()) {
-    // Note that per both C89 and C99, this is always legal, even
-    // if ptype is an incomplete type or void.
-    // It would be possible to warn about dereferencing a
-    // void pointer, but it's completely well-defined,
-    // and such a warning is unlikely to catch any mistakes.
+QualType Sema::CheckIndirectionOperand(Expr *Op, SourceLocation OpLoc) {
+  UsualUnaryConversions(Op);
+  QualType Ty = Op->getType();
+  
+  // Note that per both C89 and C99, this is always legal, even if ptype is an
+  // incomplete type or void.  It would be possible to warn about dereferencing
+  // a void pointer, but it's completely well-defined, and such a warning is
+  // unlikely to catch any mistakes.
+  if (const PointerType *PT = Ty->getAsPointerType())
     return PT->getPointeeType();
-  }
+  
   Diag(OpLoc, diag::err_typecheck_indirection_requires_pointer)
-    << qType.getAsString() << op->getSourceRange();
+    << Ty << Op->getSourceRange();
   return QualType();
 }
 





More information about the cfe-commits mailing list