[PATCH] Fix for crash due to g++.old-deja/g++.other/using3.C

Dinesh Dwivedi dinesh.d at samsung.com
Wed Mar 12 00:37:22 PDT 2014


Hi rjmccall, rsmith,

Following patch fixes crash in clang with attached test case [taken from g++.old-deja/g++.other/using3.C].

Issue:
	Test is trying to make using declaration for a non-existing member in base class in derived class and expect error 
	while compiling. Current clang code handles normal cases properly.
	
	Problem arises when base class is typedefed to a type constructed in-place. As using declaration is referring to a 
	non-existing member, normal lookup fails and while trying typo-correction, clang returns typedef declaration as 
	possible alternative, which is not a record type and can not be type casted to EnumDecl/ RecordDecl/ CXXRecordDecl.
	
	But Sema::CheckUsingShadowDecl() assumes otherwise and tries to typecast it to CXXRecordDecl without any check while 
	checking if referred type is from base class or not. This results in crash in clang.
	
Solution:
	I looked for ways to get CXXRecordDecl from TypedefDecl but did not find any. I found function like getUnderlyingDecl() 
	but they just work with UsingDecls and ObjCCompatibleAliasDecls. Moreover, for any existing member, clang find proper 
	declaration and code works fine.
	
	So I have added a check in Sema::CheckUsingShadowDecl() to bypass base class check if referred type in using declaration 
	is not in a record type. A proper fix will be if we can get proper RecordDecl from TypedefDecl and use it for this check 
	or handle TypedefDecl case separately.

http://llvm-reviews.chandlerc.com/D3051

Files:
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/using-decl-2.cpp

Index: lib/Sema/SemaDeclCXX.cpp
===================================================================
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -7164,28 +7164,29 @@
   if (!getLangOpts().CPlusPlus11 && CurContext->isRecord()) {
     DeclContext *OrigDC = Orig->getDeclContext();
 
-    // Handle enums and anonymous structs.
+    if (OrigDC->isRecord()) {
+      // Handle enums and anonymous structs.
     if (isa<EnumDecl>(OrigDC)) OrigDC = OrigDC->getParent();
-    CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
-    while (OrigRec->isAnonymousStructOrUnion())
-      OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+      CXXRecordDecl *OrigRec = cast<CXXRecordDecl>(OrigDC);
+      while (OrigRec->isAnonymousStructOrUnion())
+        OrigRec = cast<CXXRecordDecl>(OrigRec->getDeclContext());
+
+      if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
+        if (OrigDC == CurContext) {
+          Diag(Using->getLocation(),
+               diag::err_using_decl_nested_name_specifier_is_current_class)
+              << Using->getQualifierLoc().getSourceRange();
+          Diag(Orig->getLocation(), diag::note_using_decl_target);
+          return true;
+        }
 
-    if (cast<CXXRecordDecl>(CurContext)->isProvablyNotDerivedFrom(OrigRec)) {
-      if (OrigDC == CurContext) {
-        Diag(Using->getLocation(),
-             diag::err_using_decl_nested_name_specifier_is_current_class)
-          << Using->getQualifierLoc().getSourceRange();
+        Diag(Using->getQualifierLoc().getBeginLoc(),
+             diag::err_using_decl_nested_name_specifier_is_not_base_class)
+            << Using->getQualifier() << cast<CXXRecordDecl>(CurContext)
+            << Using->getQualifierLoc().getSourceRange();
         Diag(Orig->getLocation(), diag::note_using_decl_target);
         return true;
       }
-
-      Diag(Using->getQualifierLoc().getBeginLoc(),
-           diag::err_using_decl_nested_name_specifier_is_not_base_class)
-        << Using->getQualifier()
-        << cast<CXXRecordDecl>(CurContext)
-        << Using->getQualifierLoc().getSourceRange();
-      Diag(Orig->getLocation(), diag::note_using_decl_target);
-      return true;
     }
   }
 
Index: test/SemaCXX/using-decl-2.cpp
===================================================================
--- /dev/null
+++ test/SemaCXX/using-decl-2.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct A {
+  A();
+};
+
+typedef struct {
+  A i;
+} S; // expected-note {{declared here}}
+
+struct B : S {
+  using S::S; // expected-error {{no member named 'S' in 'S'}}
+};
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D3051.1.patch
Type: text/x-patch
Size: 2630 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20140312/7f316d55/attachment.bin>


More information about the cfe-commits mailing list