]> granicus.if.org Git - clang/commitdiff
[MSVC] Fix stack overflow in unqualified type lookup logic, by Will
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 31 May 2016 06:21:27 +0000 (06:21 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 31 May 2016 06:21:27 +0000 (06:21 +0000)
Wilson.

An unqualified lookup for in base classes may cause stack overflow if
the base class is a specialization of current class.
Patch by Will Wilson.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@271251 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/SemaTemplate/ms-lookup-template-base-classes.cpp

index f845a65a000bc88bce97393d4cfd37223d13c730..64da16add18a40e440b8233cccf425fac497df34 100644 (file)
@@ -163,11 +163,17 @@ lookupUnqualifiedTypeNameInBase(Sema &S, const IdentifierInfo &II,
       auto *TD = TST->getTemplateName().getAsTemplateDecl();
       if (!TD)
         continue;
-      auto *BasePrimaryTemplate =
-          dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl());
-      if (!BasePrimaryTemplate)
-        continue;
-      BaseRD = BasePrimaryTemplate;
+      if (auto *BasePrimaryTemplate =
+          dyn_cast_or_null<CXXRecordDecl>(TD->getTemplatedDecl())) {
+        if (BasePrimaryTemplate->getCanonicalDecl() != RD->getCanonicalDecl())
+          BaseRD = BasePrimaryTemplate;
+        else if (auto *CTD = dyn_cast<ClassTemplateDecl>(TD)) {
+          if (const ClassTemplatePartialSpecializationDecl *PS =
+                  CTD->findPartialSpecialization(Base.getType()))
+            if (PS->getCanonicalDecl() != RD->getCanonicalDecl())
+              BaseRD = PS;
+        }
+      }
     }
     if (BaseRD) {
       for (NamedDecl *ND : BaseRD->lookup(&II)) {
index 51d19cef382f37e4ad797d2d30429e0c6ec7b9a6..6afc7091260dcde091f6c41686d97db701638643 100644 (file)
@@ -603,3 +603,32 @@ struct Base {
 template struct UseUnqualifiedTypeNames<Base>;
 struct BadBase { };
 template struct UseUnqualifiedTypeNames<BadBase>; // expected-note-re 2 {{in instantiation {{.*}} requested here}}
+
+namespace partial_template_lookup {
+
+class Bar;
+class Spare;
+
+template <class T, class X = Bar>
+class FooTemplated;
+
+class FooBase {
+public:
+  typedef int BaseTypedef;
+};
+
+// Partial template spec (unused)
+template <class T>
+class FooTemplated<T, Spare> {};
+
+// Partial template spec (used)
+template <class T>
+class FooTemplated<T, Bar> : public FooBase {};
+
+// Full template spec
+template <class T, class X>
+class FooTemplated : public FooTemplated<T, Bar> {
+public:
+  BaseTypedef Member; // expected-warning {{unqualified lookup}}
+};
+}