]> granicus.if.org Git - clang/commitdiff
Update template diffing to handle template arguments that are declarations.
authorRichard Trieu <rtrieu@google.com>
Wed, 27 Feb 2013 01:41:53 +0000 (01:41 +0000)
committerRichard Trieu <rtrieu@google.com>
Wed, 27 Feb 2013 01:41:53 +0000 (01:41 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176153 91177308-0d34-0410-b5e6-96231b3b80d8

lib/AST/ASTDiagnostic.cpp
test/Misc/diag-template-diffing.cpp

index 92b1ca0d5b17d11159a62966702445f1667b89bd..d67423ed3d29dfe20998485fa76254e7f688bb70 100644 (file)
@@ -435,6 +435,9 @@ class TemplateDiff {
       /// IsValidFromInt, IsValidToInt - Whether the APSInt's are valid.
       bool IsValidFromInt, IsValidToInt;
 
+      /// FromValueDecl, ToValueDecl - Whether the argument is a decl.
+      ValueDecl *FromValueDecl, *ToValueDecl;
+
       /// FromDefault, ToDefault - Whether the argument is a default argument.
       bool FromDefault, ToDefault;
 
@@ -444,8 +447,8 @@ class TemplateDiff {
       DiffNode(unsigned ParentNode = 0)
         : NextNode(0), ChildNode(0), ParentNode(ParentNode),
           FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0),
-          IsValidFromInt(false), IsValidToInt(false),
-          FromDefault(false), ToDefault(false), Same(false) { }
+          IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0),
+          ToValueDecl(0), FromDefault(false), ToDefault(false), Same(false) { }
     };
 
     /// FlatTree - A flattened tree used to store the DiffNodes.
@@ -501,6 +504,12 @@ class TemplateDiff {
       FlatTree[CurrentNode].ToQual = ToQual;
     }
 
+    /// SetNode - Set FromValueDecl and ToValueDecl of the current node.
+    void SetNode(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl) {
+      FlatTree[CurrentNode].FromValueDecl = FromValueDecl;
+      FlatTree[CurrentNode].ToValueDecl = ToValueDecl;
+    }
+
     /// SetSame - Sets the same flag of the current node.
     void SetSame(bool Same) {
       FlatTree[CurrentNode].Same = Same;
@@ -584,6 +593,11 @@ class TemplateDiff {
              FlatTree[ReadNode].IsValidToInt;
     }
 
+    /// NodeIsDecl - Returns true if the arguments are stored as Decl's.
+    bool NodeIsValueDecl() {
+      return FlatTree[ReadNode].FromValueDecl || FlatTree[ReadNode].ToValueDecl;
+    }
+
     /// GetNode - Gets the FromType and ToType.
     void GetNode(QualType &FromType, QualType &ToType) {
       FromType = FlatTree[ReadNode].FromType;
@@ -617,6 +631,12 @@ class TemplateDiff {
       ToQual = FlatTree[ReadNode].ToQual;
     }
 
+    /// GetNode - Gets the FromValueDecl and ToValueDecl.
+    void GetNode(ValueDecl *&FromValueDecl, ValueDecl *&ToValueDecl) {
+      FromValueDecl = FlatTree[ReadNode].FromValueDecl;
+      ToValueDecl = FlatTree[ReadNode].ToValueDecl;
+    }
+
     /// NodeIsSame - Returns true the arguments are the same.
     bool NodeIsSame() {
       return FlatTree[ReadNode].Same;
@@ -845,6 +865,7 @@ class TemplateDiff {
               dyn_cast<NonTypeTemplateParmDecl>(ParamND)) {
         Expr *FromExpr, *ToExpr;
         llvm::APSInt FromInt, ToInt;
+        ValueDecl *FromValueDecl = 0, *ToValueDecl = 0;
         unsigned ParamWidth = 128; // Safe default
         if (DefaultNTTPD->getType()->isIntegralOrEnumerationType())
           ParamWidth = Context.getIntWidth(DefaultNTTPD->getType());
@@ -852,23 +873,37 @@ class TemplateDiff {
                           FromIter->getKind() == TemplateArgument::Integral;
         bool HasToInt = !ToIter.isEnd() &&
                         ToIter->getKind() == TemplateArgument::Integral;
+        bool HasFromValueDecl =
+            !FromIter.isEnd() &&
+            FromIter->getKind() == TemplateArgument::Declaration;
+        bool HasToValueDecl =
+            !ToIter.isEnd() &&
+            ToIter->getKind() == TemplateArgument::Declaration;
+
+        assert(((!HasFromInt && !HasToInt) ||
+                (!HasFromValueDecl && !HasToValueDecl)) &&
+               "Template argument cannot be both integer and declaration");
 
         if (HasFromInt)
           FromInt = FromIter->getAsIntegral();
+        else if (HasFromValueDecl)
+          FromValueDecl = FromIter->getAsDecl();
         else
           GetExpr(FromIter, DefaultNTTPD, FromExpr);
 
         if (HasToInt)
           ToInt = ToIter->getAsIntegral();
+        else if (HasToValueDecl)
+          ToValueDecl = ToIter->getAsDecl();
         else
           GetExpr(ToIter, DefaultNTTPD, ToExpr);
 
-        if (!HasFromInt && !HasToInt) {
+        if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) {
           Tree.SetNode(FromExpr, ToExpr);
           Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr));
           Tree.SetDefault(FromIter.isEnd() && FromExpr,
                           ToIter.isEnd() && ToExpr);
-        } else {
+        } else if (HasFromInt || HasToInt) {
           if (!HasFromInt && FromExpr) {
             FromInt = FromExpr->EvaluateKnownConstInt(Context);
             HasFromInt = true;
@@ -881,6 +916,20 @@ class TemplateDiff {
           Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt));
           Tree.SetDefault(FromIter.isEnd() && HasFromInt,
                           ToIter.isEnd() && HasToInt);
+        } else {
+          if (!HasFromValueDecl && FromExpr) {
+            DeclRefExpr *DRE = cast<DeclRefExpr>(FromExpr);
+            FromValueDecl = cast<ValueDecl>(DRE->getDecl());
+          }
+          if (!HasToValueDecl && ToExpr) {
+            DeclRefExpr *DRE = cast<DeclRefExpr>(ToExpr);
+            ToValueDecl = cast<ValueDecl>(DRE->getDecl());
+          }
+          Tree.SetNode(FromValueDecl, ToValueDecl);
+          Tree.SetSame(FromValueDecl->getCanonicalDecl() ==
+                       ToValueDecl->getCanonicalDecl());
+          Tree.SetDefault(FromIter.isEnd() && FromValueDecl,
+                          ToIter.isEnd() && ToValueDecl);
         }
       }
 
@@ -1116,6 +1165,15 @@ class TemplateDiff {
                     Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame());
         return;
       }
+
+      if (Tree.NodeIsValueDecl()) {
+        ValueDecl *FromValueDecl, *ToValueDecl;
+        Tree.GetNode(FromValueDecl, ToValueDecl);
+        PrintValueDecl(FromValueDecl, ToValueDecl, Tree.FromDefault(),
+                       Tree.ToDefault(), Tree.NodeIsSame());
+        return;
+      }
+
       llvm_unreachable("Unable to deduce template difference.");
     }
 
@@ -1331,6 +1389,35 @@ class TemplateDiff {
     }
   }
 
+  
+  /// PrintDecl - Handles printing of Decl arguments, highlighting
+  /// argument differences.
+  void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl,
+                      bool FromDefault, bool ToDefault, bool Same) {
+    assert((FromValueDecl || ToValueDecl) &&
+           "Only one Decl argument may be NULL");
+
+    if (Same) {
+      OS << FromValueDecl->getName();
+    } else if (!PrintTree) {
+      OS << (FromDefault ? "(default) " : "");
+      Bold();
+      OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
+      Unbold();
+    } else {
+      OS << (FromDefault ? "[(default) " : "[");
+      Bold();
+      OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)");
+      Unbold();
+      OS << " != " << (ToDefault ? "(default) " : "");
+      Bold();
+      OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)");
+      Unbold();
+      OS << ']';
+    }
+
+  }
+
   // Prints the appropriate placeholder for elided template arguments.
   void PrintElideArgs(unsigned NumElideArgs, unsigned Indent) {
     if (PrintTree) {
index c6fc32d1b34959eba92637e41f5fc02967c100cc..6be705511db0540658d8683eeac3867d624ab7af 100644 (file)
@@ -869,6 +869,40 @@ namespace rdar12931988 {
   }
 }
 
+namespace ValueDecl {
+  int int1, int2, default_int;
+  template <const int& T = default_int>
+  struct S {};
+
+  typedef S<int1> T1;
+  typedef S<int2> T2;
+  typedef S<> TD;
+
+  void test() {
+    T1 t1;
+    T2 t2;
+    TD td;
+
+    t1 = t2;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'S<int2>' to 'S<int1>'
+
+    t2 = t1;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'S<int1>' to 'S<int2>'
+
+    td = t1;
+    // TODO: Find out why (default) isn't printed on second template.
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'S<int1>' to 'S<default_int>'
+
+    t2 = td;
+    // CHECK-ELIDE-NOTREE: no viable overloaded '='
+    // CHECK-ELIDE-NOTREE: no known conversion from 'S<(default) default_int>' to 'S<int2>'
+
+  }
+}
+
 // CHECK-ELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-NOELIDE-NOTREE: {{[0-9]*}} errors generated.
 // CHECK-ELIDE-TREE: {{[0-9]*}} errors generated.