]> granicus.if.org Git - clang/commitdiff
In Microsoft mode, within class scope, if a CXXScopeSpec's type is equal to the type...
authorFrancois Pichet <pichet2000@gmail.com>
Wed, 13 Apr 2011 02:38:49 +0000 (02:38 +0000)
committerFrancois Pichet <pichet2000@gmail.com>
Wed, 13 Apr 2011 02:38:49 +0000 (02:38 +0000)
This fixes 1 error when parsing the MSVC 2008 header files.
Example:

template<class T> class A {
public:
  typedef int TYPE;
};
template<class T> class B : public A<T> {
public:
  A<T>::TYPE a; // no typename required because A<T> is a base class.
};

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

include/clang/Basic/DiagnosticSemaKinds.td
include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
test/SemaCXX/MicrosoftExtensions.cpp

index 1bdcb88445a199661e292a9c8a4eaadf6579d67b..9d0c2c4f2484480622accef721666167831c9357 100644 (file)
@@ -1946,6 +1946,8 @@ def note_typename_refers_here : Note<
     "referenced member %0 is declared here">;
 def err_typename_missing : Error<
   "missing 'typename' prior to dependent type name '%0%1'">;
+def war_typename_missing : ExtWarn<
+  "missing 'typename' prior to dependent type name '%0%1'">;
 def ext_typename_outside_of_template : ExtWarn<
   "'typename' occurs outside of a template">, InGroup<CXX0x>;
 def err_typename_refers_to_using_value_decl : Error<
index e931fb6603ae466dcff392b74e0fe32c8ecbfced..1169b50f852933c95d581456439d9e6e87e6196d 100644 (file)
@@ -799,6 +799,7 @@ public:
                          ParsedType ObjectType = ParsedType(),
                          bool WantNontrivialTypeSourceInfo = false);
   TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
+  bool isMicrosoftMissingTypename(const CXXScopeSpec *SS);
   bool DiagnoseUnknownTypeName(const IdentifierInfo &II,
                                SourceLocation IILoc,
                                Scope *S,
index a2249c787b542d09d0c8ee45ccd8dfb7e735cec4..4338ddaa1aaeb864ba40f803c2d4f2b21c833f8c 100644 (file)
@@ -250,6 +250,33 @@ DeclSpec::TST Sema::isTagName(IdentifierInfo &II, Scope *S) {
   return DeclSpec::TST_unspecified;
 }
 
+/// isMicrosoftMissingTypename - In Microsoft mode, within class scope,
+/// if a CXXScopeSpec's type is equal to the type of one of the base classes
+/// then downgrade the missing typename error to a warning.
+/// This is needed for MSVC compatibility; Example:
+/// @code
+/// template<class T> class A {
+/// public:
+///   typedef int TYPE;
+/// };
+/// template<class T> class B : public A<T> {
+/// public:
+///   A<T>::TYPE a; // no typename required because A<T> is a base class.
+/// };
+/// @endcode
+bool Sema::isMicrosoftMissingTypename(const CXXScopeSpec *SS) {
+  if (CurContext->isRecord()) {
+    const Type* Ty = SS->getScopeRep()->getAsType();
+
+    CXXRecordDecl *RD = cast<CXXRecordDecl>(CurContext);
+    for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(),
+          BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base)
+      if (Context.hasSameUnqualifiedType(QualType(Ty, 1), Base->getType()))
+        return true;
+  } 
+  return false;
+}
+
 bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, 
                                    SourceLocation IILoc,
                                    Scope *S,
@@ -327,7 +354,11 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II,
     Diag(IILoc, diag::err_typename_nested_not_found) 
       << &II << DC << SS->getRange();
   else if (isDependentScopeSpecifier(*SS)) {
-    Diag(SS->getRange().getBegin(), diag::err_typename_missing)
+    unsigned DiagID = diag::err_typename_missing;
+    if (getLangOptions().Microsoft && isMicrosoftMissingTypename(SS))
+      DiagID = diag::war_typename_missing;
+
+    Diag(SS->getRange().getBegin(), DiagID)
       << (NestedNameSpecifier *)SS->getScopeRep() << II.getName()
       << SourceRange(SS->getRange().getBegin(), IILoc)
       << FixItHint::CreateInsertion(SS->getRange().getBegin(), "typename ");
index 2287d26fa8fa78da7790e2bd60a5b35588316858..c2a32b4c40707f81313bfd0a87046f09f26e7a42 100644 (file)
@@ -136,3 +136,35 @@ public:
 template <class T>
 void BB<T>::f(int g = 0) { } // expected-warning {{redefinition of default argument}}
 
+
+namespace MissingTypename {
+
+template<class T> class A {
+public:
+        typedef int TYPE;
+};
+
+template<class T> class B {
+public:
+        typedef int TYPE;
+};
+
+
+template<class T, class U>
+class C : private A<T>, public B<U> {
+public:
+   typedef A<T> Base1;
+   typedef B<U> Base2;
+   typedef A<U> Base3;
+
+   A<T>::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}}
+   Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}}
+
+   B<U>::TYPE a3; // expected-warning {{missing 'typename' prior to dependent type name}}
+   Base2::TYPE a4; // expected-warning {{missing 'typename' prior to dependent type name}}
+
+   A<U>::TYPE a5; // expected-error {{missing 'typename' prior to dependent type name}}
+   Base3::TYPE a6; // expected-error {{missing 'typename' prior to dependent type name}}
+ };
+
+}
\ No newline at end of file