avt77 created this revision.
avt77 added a reviewer: rnk.
avt77 added a subscriber: cfe-commits.

This is the first patch to fix clang-cl incompatibility prohibited to compile 
the header file. The patch covers the following case:

class CCommandBarCtrlBase {
public:
  typedef int CMsgHookMap;
};

template <class T>
class CCommandBarCtrlImpl : public T {
public:
  void foo() {
    void *p = new CMsgHookMap; // "new typename T::CMsgHookMap" works fine
  }
};

void bar() {
  CCommandBarCtrlImpl<CCommandBarCtrlBase> x;
  x.foo();
}

http://reviews.llvm.org/D19479

Files:
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaLookup.cpp
  test/Sema/dtp-lookup-in-base-classes.cpp

Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp
+++ lib/Parse/ParseDecl.cpp
@@ -2995,6 +2995,27 @@
         TypeRep = Actions.ActOnDelayedDefaultTemplateArg(
             *Tok.getIdentifierInfo(), Tok.getLocation());
       }
+      if (!TypeRep && DSContext == DSC_type_specifier &&
+          Actions.CurContext->isDependentContext() &&
+          getLangOpts().MSVCCompat) {
+        IdentifierInfo *II = Tok.getIdentifierInfo();
+        Actions.DiagnoseUnknownTypeName(II, Tok.getLocation(), getCurScope(),
+                                        nullptr, TypeRep, true);
+        if (TypeRep) {
+          // The action has suggested that the type TypeRep could be used.
+          // Set that as the type in the declaration specifiers,
+          // consume the would-be type name token, and we're done.
+          const char *PrevSpec;
+          unsigned DiagID;
+          DS.SetTypeSpecType(DeclSpec::TST_typename, Tok.getLocation(),
+                             PrevSpec, DiagID, TypeRep,
+                             Actions.getASTContext().getPrintingPolicy());
+          DS.SetRangeEnd(Tok.getLocation());
+          ConsumeToken();
+          // There may be other declaration specifiers after this.
+          continue;
+        }
+      }
 
       // If this is not a typedef name, don't parse it as part of the declspec,
       // it must be an implicit int or an error.
Index: lib/Sema/SemaLookup.cpp
===================================================================
--- lib/Sema/SemaLookup.cpp
+++ lib/Sema/SemaLookup.cpp
@@ -4437,13 +4437,6 @@
       DisableTypoCorrection)
     return nullptr;
 
-  // In Microsoft mode, don't perform typo correction in a template member
-  // function dependent context because it interferes with the "lookup into
-  // dependent bases of class templates" feature.
-  if (getLangOpts().MSVCCompat && CurContext->isDependentContext() &&
-      isa<CXXMethodDecl>(CurContext))
-    return nullptr;
-
   // We only attempt to correct typos for identifiers.
   IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
   if (!Typo)
Index: lib/Sema/SemaDecl.cpp
===================================================================
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -207,9 +207,15 @@
     if (RD && RD->getDescribedClassTemplate())
       FoundTypeDecl = lookupUnqualifiedTypeNameInBase(S, II, NameLoc, RD);
   }
-  if (FoundTypeDecl != UnqualifiedTypeNameLookupResult::FoundType)
-    return nullptr;
-
+  if (FoundTypeDecl != UnqualifiedTypeNameLookupResult::FoundType) {
+    ParsedType Result = nullptr;
+    if (S.getLangOpts().MSVCCompat && S.CurContext->isDependentContext()) {
+      auto *II2 = const_cast<IdentifierInfo *>(&II);
+      S.DiagnoseUnknownTypeName(II2, NameLoc, S.getCurScope(), nullptr, Result,
+                                false, true);
+    }
+    return Result;
+  }
   // We found some types in dependent base classes.  Recover as if the user
   // wrote 'typename MyClass::II' instead of 'II'.  We'll fully resolve the
   // lookup during template instantiation.
@@ -553,31 +559,31 @@
   return CurContext->isFunctionOrMethod() || S->isFunctionPrototypeScope();
 }
 
-void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II,
-                                   SourceLocation IILoc,
-                                   Scope *S,
-                                   CXXScopeSpec *SS,
+void Sema::DiagnoseUnknownTypeName(IdentifierInfo *&II, SourceLocation IILoc,
+                                   Scope *S, CXXScopeSpec *SS,
                                    ParsedType &SuggestedType,
-                                   bool AllowClassTemplates) {
+                                   bool AllowClassTemplates,
+                                   bool AllowInvalid) {
   // We don't have anything to suggest (yet).
   SuggestedType = nullptr;
 
   // There may have been a typo in the name of the type. Look up typo
   // results, in case we have something that we can suggest.
   if (TypoCorrection Corrected =
           CorrectTypo(DeclarationNameInfo(II, IILoc), LookupOrdinaryName, S, SS,
                       llvm::make_unique<TypeNameValidatorCCC>(
-                          false, false, AllowClassTemplates),
+                          AllowInvalid, false, AllowClassTemplates),
                       CTK_ErrorRecovery)) {
     if (Corrected.isKeyword()) {
       // We corrected to a keyword.
       diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest) << II);
       II = Corrected.getCorrectionAsIdentifierInfo();
     } else {
       // We found a similarly-named type or interface; suggest that.
       if (!SS || !SS->isSet()) {
-        diagnoseTypo(Corrected,
-                     PDiag(diag::err_unknown_typename_suggest) << II);
+        if (!AllowInvalid)
+          diagnoseTypo(Corrected, PDiag(diag::err_unknown_typename_suggest)
+                                      << II);
       } else if (DeclContext *DC = computeDeclContext(*SS, false)) {
         std::string CorrectedStr(Corrected.getAsString(getLangOpts()));
         bool DroppedSpecifier = Corrected.WillReplaceSpecifier() &&
@@ -624,10 +630,11 @@
 
   // FIXME: Should we move the logic that tries to recover from a missing tag
   // (struct, union, enum) from Parser::ParseImplicitInt here, instead?
-  
-  if (!SS || (!SS->isSet() && !SS->isInvalid()))
-    Diag(IILoc, diag::err_unknown_typename) << II;
-  else if (DeclContext *DC = computeDeclContext(*SS, false))
+
+  if (!SS || (!SS->isSet() && !SS->isInvalid())) {
+    if (!AllowInvalid)
+      Diag(IILoc, diag::err_unknown_typename) << II;
+  } else if (DeclContext *DC = computeDeclContext(*SS, false))
     Diag(IILoc, diag::err_typename_nested_not_found) 
       << II << DC << SS->getRange();
   else if (isDependentScopeSpecifier(*SS)) {
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -1495,12 +1495,11 @@
                          IdentifierInfo **CorrectedII = nullptr);
   TypeSpecifierType isTagName(IdentifierInfo &II, Scope *S);
   bool isMicrosoftMissingTypename(const CXXScopeSpec *SS, Scope *S);
-  void DiagnoseUnknownTypeName(IdentifierInfo *&II,
-                               SourceLocation IILoc,
-                               Scope *S,
-                               CXXScopeSpec *SS,
+  void DiagnoseUnknownTypeName(IdentifierInfo *&II, SourceLocation IILoc,
+                               Scope *S, CXXScopeSpec *SS,
                                ParsedType &SuggestedType,
-                               bool AllowClassTemplates = false);
+                               bool AllowClassTemplates = false,
+                               bool AllowInvalid = false);
 
   /// \brief For compatibility with MSVC, we delay parsing of some default
   /// template type arguments until instantiation time.  Emits a warning and
Index: test/Sema/dtp-lookup-in-base-classes.cpp
===================================================================
--- test/Sema/dtp-lookup-in-base-classes.cpp
+++ test/Sema/dtp-lookup-in-base-classes.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1  %s -fms-compatibility -triple=i386-pc-win32 -verify
+// expected-no-diagnostics
+
+class CCommandBarCtrlBase {
+public:
+  typedef int CMsgHookMap;
+};
+
+template <class T>
+class CCommandBarCtrlImpl : public T {
+  public:
+    CMsgHookMap zzzz;
+    void foo(CMsgHookMap hook) {
+      void *pppp = new CMsgHookMap;
+      CMsgHookMap xxx = 6666;
+      zzzz = 7777;
+    }
+};
+
+void bar() {
+  CCommandBarCtrlImpl<CCommandBarCtrlBase> x;
+  x.foo(12345);
+}
+
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to