r181365 - Fix crash on invalid in template type diffing.

Richard Trieu rtrieu at google.com
Tue May 7 14:36:24 PDT 2013


Author: rtrieu
Date: Tue May  7 16:36:24 2013
New Revision: 181365

URL: http://llvm.org/viewvc/llvm-project?rev=181365&view=rev
Log:
Fix crash on invalid in template type diffing.

This is a fix for PR15895, where Clang will crash when trying to print a
template diff and the template uses an address of operator.  This resulted
from expecting a DeclRefExpr when the Expr could have also been
UnaryOperator->DeclRefExpr.

Modified:
    cfe/trunk/lib/AST/ASTDiagnostic.cpp
    cfe/trunk/test/Misc/diag-template-diffing.cpp

Modified: cfe/trunk/lib/AST/ASTDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDiagnostic.cpp?rev=181365&r1=181364&r2=181365&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDiagnostic.cpp (original)
+++ cfe/trunk/lib/AST/ASTDiagnostic.cpp Tue May  7 16:36:24 2013
@@ -459,6 +459,10 @@ class TemplateDiff {
       /// FromValueDecl, ToValueDecl - Whether the argument is a decl.
       ValueDecl *FromValueDecl, *ToValueDecl;
 
+      /// FromAddressOf, ToAddressOf - Whether the ValueDecl needs an address of
+      /// operator before it.
+      bool FromAddressOf, ToAddressOf;
+
       /// FromDefault, ToDefault - Whether the argument is a default argument.
       bool FromDefault, ToDefault;
 
@@ -469,7 +473,8 @@ class TemplateDiff {
         : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode),
           FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0),
           IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0),
-          ToValueDecl(0), FromDefault(false), ToDefault(false), Same(false) { }
+          ToValueDecl(0), FromAddressOf(false), ToAddressOf(false),
+          FromDefault(false), ToDefault(false), Same(false) { }
     };
 
     /// FlatTree - A flattened tree used to store the DiffNodes.
@@ -526,9 +531,12 @@ class TemplateDiff {
     }
 
     /// SetNode - Set FromValueDecl and ToValueDecl of the current node.
-    void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl) {
+    void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
+                 bool FromAddressOf, bool ToAddressOf) {
       FlatTree[CurrentNode].FromValueDecl = FromValueDecl;
       FlatTree[CurrentNode].ToValueDecl = ToValueDecl;
+      FlatTree[CurrentNode].FromAddressOf = FromAddressOf;
+      FlatTree[CurrentNode].ToAddressOf = ToAddressOf;
     }
 
     /// SetSame - Sets the same flag of the current node.
@@ -620,9 +628,12 @@ class TemplateDiff {
     }
 
     /// GetNode - Gets the FromValueDecl and ToValueDecl.
-    void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl) {
+    void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl,
+                 bool &FromAddressOf, bool &ToAddressOf) {
       FromValueDecl = FlatTree[ReadNode].FromValueDecl;
       ToValueDecl = FlatTree[ReadNode].ToValueDecl;
+      FromAddressOf = FlatTree[ReadNode].FromAddressOf;
+      ToAddressOf = FlatTree[ReadNode].ToAddressOf;
     }
 
     /// NodeIsSame - Returns true the arguments are the same.
@@ -942,7 +953,14 @@ class TemplateDiff {
             FromValueDecl = GetValueDecl(FromIter, FromExpr);
           if (!HasToValueDecl && ToExpr)
             ToValueDecl = GetValueDecl(ToIter, ToExpr);
-          Tree.SetNode(FromValueDecl, ToValueDecl);
+          QualType ArgumentType = DefaultNTTPD->getType();
+          bool FromAddressOf = FromValueDecl &&
+                               !ArgumentType->isReferenceType() &&
+                               !FromValueDecl->getType()->isArrayType();
+          bool ToAddressOf = ToValueDecl &&
+                             !ArgumentType->isReferenceType() &&
+                             !ToValueDecl->getType()->isArrayType();
+          Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
           Tree.SetSame(FromValueDecl && ToValueDecl &&
                        FromValueDecl->getCanonicalDecl() ==
                        ToValueDecl->getCanonicalDecl());
@@ -1080,7 +1098,7 @@ class TemplateDiff {
     return ArgExpr->EvaluateKnownConstInt(Context);
   }
 
-  /// GetValueDecl - Retrieves the template integer argument, including
+  /// GetValueDecl - Retrieves the template Decl argument, including
   /// default expression argument.
   ValueDecl *GetValueDecl(const TSTiterator &Iter, Expr *ArgExpr) {
     // Default, value-depenedent expressions require fetching
@@ -1095,7 +1113,12 @@ class TemplateDiff {
         default:
           assert(0 && "Unexpected template argument kind");
       }
-    return cast<DeclRefExpr>(ArgExpr)->getDecl();
+    DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr);
+    if (!DRE) {
+      DRE = cast<DeclRefExpr>(cast<UnaryOperator>(ArgExpr)->getSubExpr());
+    }
+
+    return DRE->getDecl();
   }
 
   /// GetTemplateDecl - Retrieves the template template arguments, including
@@ -1228,9 +1251,10 @@ class TemplateDiff {
       }
       case DiffTree::Declaration: {
         ValueDecl *FromValueDecl, *ToValueDecl;
-        Tree.GetNode(FromValueDecl, ToValueDecl);
-        PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(),
-                       Tree.ToDefault(), Tree.NodeIsSame());
+        bool FromAddressOf, ToAddressOf;
+        Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf);
+        PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf,
+                       Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
         return;
       }
       case DiffTree::Template: {
@@ -1478,7 +1502,8 @@ class TemplateDiff {
   /// PrintDecl - Handles printing of Decl arguments, highlighting
   /// argument differences.
   void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
-                      bool FromDefault, bool ToDefault, bool Same) {
+                      bool FromAddressOf, bool ToAddressOf, bool FromDefault,
+                      bool ToDefault, bool Same) {
     assert((FromValueDecl || ToValueDecl) &&
            "Only one Decl argument may be NULL");
 
@@ -1487,15 +1512,21 @@ class TemplateDiff {
     } else if (!PrintTree) {
       OS << (FromDefault ? "(default) " : "");
       Bold();
+      if (FromAddressOf)
+        OS << "&";
       OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
       Unbold();
     } else {
       OS << (FromDefault ? "[(default) " : "[");
       Bold();
+      if (FromAddressOf)
+        OS << "&";
       OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
       Unbold();
       OS << " != " << (ToDefault ? "(default) " : "");
       Bold();
+      if (ToAddressOf)
+        OS << "&";
       OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)");
       Unbold();
       OS << ']';

Modified: cfe/trunk/test/Misc/diag-template-diffing.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Misc/diag-template-diffing.cpp?rev=181365&r1=181364&r2=181365&view=diff
==============================================================================
--- cfe/trunk/test/Misc/diag-template-diffing.cpp (original)
+++ cfe/trunk/test/Misc/diag-template-diffing.cpp Tue May  7 16:36:24 2013
@@ -1002,6 +1002,33 @@ namespace VariadicDefault {
   }
 }
 
+namespace PointerArguments {
+  template <int *p> class T {};
+  template <int* ...> class U {};
+  int a, b, c;
+  int z[5];
+  void test() {
+    T<&a> ta;
+    T<z> tz;
+    T<&b> tb(ta);
+    // CHECK-ELIDE-NOTREE: no matching constructor for initialization of 'T<&b>'
+    // CHECK-ELIDE-NOTREE: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'T<&a>' to 'const T<&b>' for 1st argument
+    T<&c> tc(tz);
+    // CHECK-ELIDE-NOTREE: no matching constructor for initialization of 'T<&c>'
+    // CHECK-ELIDE-NOTREE: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'T<z>' to 'const T<&c>' for 1st argument
+
+    U<&a, &a> uaa;
+    U<&b> ub(uaa);
+    // CHECK-ELIDE-NOTREE: no matching constructor for initialization of 'U<&b>'
+    // CHECK-ELIDE-NOTREE: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'U<&a, &a>' to 'const U<&b, (no argument)>' for 1st argument
+
+    U<&b, &b, &b> ubbb(uaa);
+    // CHECK-ELIDE-NOTREE: no matching constructor for initialization of 'U<&b, &b, &b>'
+    // CHECK-ELIDE-NOTREE: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'U<&a, &a, (no argument)>' to 'const U<&b, &b, &b>' for 1st argument
+
+  }
+}
+
 // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.





More information about the cfe-commits mailing list