r188821 - During typo correction, check for an exact match in an unimported module. If we

Richard Smith richard-llvm at metafoo.co.uk
Tue Aug 20 13:35:19 PDT 2013


Author: rsmith
Date: Tue Aug 20 15:35:18 2013
New Revision: 188821

URL: http://llvm.org/viewvc/llvm-project?rev=188821&view=rev
Log:
During typo correction, check for an exact match in an unimported module. If we
find one, then report the error as a missing import instead of as a typo.

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Lookup.h
    cfe/trunk/include/clang/Sema/TypoCorrection.h
    cfe/trunk/lib/Sema/SemaLookup.cpp
    cfe/trunk/test/Modules/auto-module-import.m
    cfe/trunk/test/Modules/decldef.m
    cfe/trunk/test/Modules/decldef.mm
    cfe/trunk/test/Modules/normal-module-map.cpp
    cfe/trunk/test/Modules/subframeworks.m
    cfe/trunk/test/Modules/submodules.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Aug 20 15:35:18 2013
@@ -6637,6 +6637,8 @@ def err_module_private_local : Error<
 def err_module_private_local_class : Error<
   "local %select{struct|interface|union|class|enum}0 cannot be declared "
   "__module_private__">;
+def err_module_private_declaration : Error<
+  "declaration of %0 must be imported from module '%1' before it is required">;
 def err_module_private_definition : Error<
   "definition of %0 must be imported from module '%1' before it is required">;
 }

Modified: cfe/trunk/include/clang/Sema/Lookup.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Lookup.h?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Lookup.h (original)
+++ cfe/trunk/include/clang/Sema/Lookup.h Tue Aug 20 15:35:18 2013
@@ -690,6 +690,11 @@ public:
   /// \brief Destroys the visible declaration consumer.
   virtual ~VisibleDeclConsumer();
 
+  /// \brief Determine whether hidden declarations (from unimported
+  /// modules) should be given to this consumer. By default, they
+  /// are not included.
+  virtual bool includeHiddenDecls() const;
+
   /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a
   /// declaration visible from the current scope or context.
   ///

Modified: cfe/trunk/include/clang/Sema/TypoCorrection.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TypoCorrection.h?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/TypoCorrection.h (original)
+++ cfe/trunk/include/clang/Sema/TypoCorrection.h Tue Aug 20 15:35:18 2013
@@ -43,7 +43,8 @@ public:
                  unsigned QualifierDistance = 0)
       : CorrectionName(Name), CorrectionNameSpec(NNS),
         CharDistance(CharDistance), QualifierDistance(QualifierDistance),
-        CallbackDistance(0), ForceSpecifierReplacement(false) {
+        CallbackDistance(0), ForceSpecifierReplacement(false),
+        RequiresImport(false) {
     if (NameDecl)
       CorrectionDecls.push_back(NameDecl);
   }
@@ -52,7 +53,7 @@ public:
                  unsigned CharDistance = 0)
       : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS),
         CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
-        ForceSpecifierReplacement(false) {
+        ForceSpecifierReplacement(false), RequiresImport(false) {
     if (Name)
       CorrectionDecls.push_back(Name);
   }
@@ -61,11 +62,12 @@ public:
                  unsigned CharDistance = 0)
       : CorrectionName(Name), CorrectionNameSpec(NNS),
         CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0),
-        ForceSpecifierReplacement(false) {}
+        ForceSpecifierReplacement(false), RequiresImport(false) {}
 
   TypoCorrection()
       : CorrectionNameSpec(0), CharDistance(0), QualifierDistance(0),
-        CallbackDistance(0), ForceSpecifierReplacement(false) {}
+        CallbackDistance(0), ForceSpecifierReplacement(false),
+        RequiresImport(false) {}
 
   /// \brief Gets the DeclarationName of the typo correction
   DeclarationName getCorrection() const { return CorrectionName; }
@@ -134,13 +136,19 @@ public:
   DeclClass *getCorrectionDeclAs() const {
     return dyn_cast_or_null<DeclClass>(getCorrectionDecl());
   }
-  
+
   /// \brief Clears the list of NamedDecls before adding the new one.
   void setCorrectionDecl(NamedDecl *CDecl) {
     CorrectionDecls.clear();
     addCorrectionDecl(CDecl);
   }
 
+  /// \brief Clears the list of NamedDecls and adds the given set.
+  void setCorrectionDecls(ArrayRef<NamedDecl*> Decls) {
+    CorrectionDecls.clear();
+    CorrectionDecls.insert(CorrectionDecls.begin(), Decls.begin(), Decls.end());
+  }
+
   /// \brief Add the given NamedDecl to the list of NamedDecls that are the
   /// declarations associated with the DeclarationName of this TypoCorrection
   void addCorrectionDecl(NamedDecl *CDecl);
@@ -206,6 +214,11 @@ public:
   }
   const_decl_iterator end() const { return CorrectionDecls.end(); }
 
+  /// \brief Returns whether this typo correction is correcting to a
+  /// declaration that was declared in a module that has not been imported.
+  bool requiresImport() const { return RequiresImport; }
+  void setRequiresImport(bool Req) { RequiresImport = Req; }
+
 private:
   bool hasCorrectionDecl() const {
     return (!isKeyword() && !CorrectionDecls.empty());
@@ -220,6 +233,7 @@ private:
   unsigned CallbackDistance;
   SourceRange CorrectionRange;
   bool ForceSpecifierReplacement;
+  bool RequiresImport;
 };
 
 /// @brief Base class for callback objects used by Sema::CorrectTypo to check

Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Aug 20 15:35:18 2013
@@ -1229,13 +1229,13 @@ bool LookupResult::isVisibleSlow(Sema &S
 ///
 /// \returns D, or a visible previous declaration of D, whichever is more recent
 /// and visible. If no declaration of D is visible, returns null.
-NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
-  assert(!isVisible(SemaRef, D) && "not in slow case");
+static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
+  assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case");
 
   for (Decl::redecl_iterator RD = D->redecls_begin(), RDEnd = D->redecls_end();
        RD != RDEnd; ++RD) {
     if (NamedDecl *ND = dyn_cast<NamedDecl>(*RD)) {
-      if (isVisible(SemaRef, ND))
+      if (LookupResult::isVisible(SemaRef, ND))
         return ND;
     }
   }
@@ -1243,6 +1243,10 @@ NamedDecl *LookupResult::getAcceptableDe
   return 0;
 }
 
+NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const {
+  return findAcceptableDecl(SemaRef, D);
+}
+
 /// @brief Perform unqualified name lookup starting from a given
 /// scope.
 ///
@@ -2900,6 +2904,8 @@ void Sema::ArgumentDependentLookup(Decla
 //----------------------------------------------------------------------------
 VisibleDeclConsumer::~VisibleDeclConsumer() { }
 
+bool VisibleDeclConsumer::includeHiddenDecls() const { return false; }
+
 namespace {
 
 class ShadowContextRAII;
@@ -3194,7 +3200,7 @@ static void LookupVisibleDecls(Scope *S,
                                   Result.getNameLoc(), Sema::LookupMemberName);
           if (ObjCInterfaceDecl *IFace = Method->getClassInterface()) {
             LookupVisibleDecls(IFace, IvarResult, /*QualifiedNameLookup=*/false,
-                               /*InBaseClass=*/false, Consumer, Visited);              
+                               /*InBaseClass=*/false, Consumer, Visited);
           }
         }
 
@@ -3259,6 +3265,7 @@ void Sema::LookupVisibleDecls(Scope *S,
 
   // Look for visible declarations.
   LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+  Result.setAllowHidden(Consumer.includeHiddenDecls());
   VisibleDeclsRecord Visited;
   if (!IncludeGlobalScope)
     Visited.visitedContext(Context.getTranslationUnitDecl());
@@ -3270,6 +3277,7 @@ void Sema::LookupVisibleDecls(DeclContex
                               VisibleDeclConsumer &Consumer,
                               bool IncludeGlobalScope) {
   LookupResult Result(*this, DeclarationName(), SourceLocation(), Kind);
+  Result.setAllowHidden(Consumer.includeHiddenDecls());
   VisibleDeclsRecord Visited;
   if (!IncludeGlobalScope)
     Visited.visitedContext(Context.getTranslationUnitDecl());
@@ -3339,7 +3347,9 @@ class TypoCorrectionConsumer : public Vi
 public:
   explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo)
     : Typo(Typo->getName()),
-      SemaRef(SemaRef) { }
+      SemaRef(SemaRef) {}
+
+  bool includeHiddenDecls() const { return true; }
 
   virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
                          bool InBaseClass);
@@ -3390,6 +3400,12 @@ void TypoCorrectionConsumer::FoundDecl(N
   if (!Name)
     return;
 
+  // Only consider visible declarations and declarations from modules with
+  // names that exactly match.
+  if (!LookupResult::isVisible(SemaRef, ND) && Name->getName() != Typo &&
+      !findAcceptableDecl(SemaRef, ND))
+    return;
+
   FoundName(Name->getName());
 }
 
@@ -3664,10 +3680,12 @@ static void LookupPotentialTypoResult(Se
                                       Scope *S, CXXScopeSpec *SS,
                                       DeclContext *MemberContext,
                                       bool EnteringContext,
-                                      bool isObjCIvarLookup) {
+                                      bool isObjCIvarLookup,
+                                      bool FindHidden) {
   Res.suppressDiagnostics();
   Res.clear();
   Res.setLookupName(Name);
+  Res.setAllowHidden(FindHidden);
   if (MemberContext) {
     if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(MemberContext)) {
       if (isObjCIvarLookup) {
@@ -3858,6 +3876,50 @@ static bool isCandidateViable(Correction
   return Candidate.getEditDistance(false) != TypoCorrection::InvalidDistance;
 }
 
+/// \brief Check whether the declarations found for a typo correction are
+/// visible, and if none of them are, convert the correction to an 'import
+/// a module' correction.
+static void checkCorrectionVisibility(Sema &SemaRef, TypoCorrection &TC,
+                                      DeclarationName TypoName) {
+  if (TC.begin() == TC.end())
+    return;
+
+  TypoCorrection::decl_iterator DI = TC.begin(), DE = TC.end();
+
+  for (/**/; DI != DE; ++DI)
+    if (!LookupResult::isVisible(SemaRef, *DI))
+      break;
+  // Nothing to do if all decls are visible.
+  if (DI == DE)
+    return;
+
+  llvm::SmallVector<NamedDecl*, 4> NewDecls(TC.begin(), DI);
+  bool AnyVisibleDecls = !NewDecls.empty();
+
+  for (/**/; DI != DE; ++DI) {
+    NamedDecl *VisibleDecl = *DI;
+    if (!LookupResult::isVisible(SemaRef, *DI))
+      VisibleDecl = findAcceptableDecl(SemaRef, *DI);
+
+    if (VisibleDecl) {
+      if (!AnyVisibleDecls) {
+        // Found a visible decl, discard all hidden ones.
+        AnyVisibleDecls = true;
+        NewDecls.clear();
+      }
+      NewDecls.push_back(VisibleDecl);
+    } else if (!AnyVisibleDecls && !(*DI)->isModulePrivate())
+      NewDecls.push_back(*DI);
+  }
+
+  if (NewDecls.empty())
+    TC = TypoCorrection();
+  else {
+    TC.setCorrectionDecls(NewDecls);
+    TC.setRequiresImport(!AnyVisibleDecls);
+  }
+}
+
 /// \brief Try to "correct" a typo in the source code by finding
 /// visible declarations whose names are similar to the name that was
 /// present in the source code.
@@ -4000,7 +4062,7 @@ TypoCorrection Sema::CorrectTypo(const D
   bool SearchNamespaces
     = getLangOpts().CPlusPlus &&
       (IsUnqualifiedLookup || (QualifiedDC && QualifiedDC->isNamespace()));
-  // In a few cases we *only* want to search for corrections bases on just
+  // In a few cases we *only* want to search for corrections based on just
   // adding or changing the nested name specifier.
   bool AllowOnlyNNSChanges = Typo->getName().size() < 3;
   
@@ -4122,7 +4184,9 @@ TypoCorrection Sema::CorrectTypo(const D
 retry_lookup:
       LookupPotentialTypoResult(*this, TmpRes, Name, S, TempSS,
                                 TempMemberContext, EnteringContext,
-                                CCC.IsObjCIvarLookup);
+                                CCC.IsObjCIvarLookup,
+                                Name == TypoName.getName() &&
+                                  !Candidate.WillReplaceSpecifier());
 
       switch (TmpRes.getResultKind()) {
       case LookupResult::NotFound:
@@ -4271,6 +4335,7 @@ retry_lookup:
 
     TypoCorrection TC = Result;
     TC.setCorrectionRange(SS, TypoName);
+    checkCorrectionVisibility(*this, TC, TypoName.getName());
     return TC;
   }
   else if (BestResults.size() > 1
@@ -4391,6 +4456,24 @@ void Sema::diagnoseTypo(const TypoCorrec
                ErrorRecovery);
 }
 
+/// Find which declaration we should import to provide the definition of
+/// the given declaration.
+static const NamedDecl *getDefinitionToImport(const NamedDecl *D) {
+  if (const VarDecl *VD = dyn_cast<VarDecl>(D))
+    return VD->getDefinition();
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
+    return FD->isDefined(FD) ? FD : 0;
+  if (const TagDecl *TD = dyn_cast<TagDecl>(D))
+    return TD->getDefinition();
+  if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
+    return ID->getDefinition();
+  if (const ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D))
+    return PD->getDefinition();
+  if (const TemplateDecl *TD = dyn_cast<TemplateDecl>(D))
+    return getDefinitionToImport(TD->getTemplatedDecl());
+  return 0;
+}
+
 /// \brief Diagnose a successfully-corrected typo. Separated from the correction
 /// itself to allow external validation of the result, etc.
 ///
@@ -4412,6 +4495,31 @@ void Sema::diagnoseTypo(const TypoCorrec
   FixItHint FixTypo = FixItHint::CreateReplacement(
       Correction.getCorrectionRange(), CorrectedStr);
 
+  // Maybe we're just missing a module import.
+  if (Correction.requiresImport()) {
+    NamedDecl *Decl = Correction.getCorrectionDecl();
+    assert(Decl && "import required but no declaration to import");
+
+    // Suggest importing a module providing the definition of this entity, if
+    // possible.
+    const NamedDecl *Def = getDefinitionToImport(Decl);
+    if (!Def)
+      Def = Decl;
+    Module *Owner = Def->getOwningModule();
+    assert(Owner && "definition of hidden declaration is not in a module");
+
+    Diag(Correction.getCorrectionRange().getBegin(),
+         diag::err_module_private_declaration)
+      << Def << Owner->getFullModuleName();
+    Diag(Def->getLocation(), diag::note_previous_declaration);
+
+    // Recover by implicitly importing this module.
+    if (!isSFINAEContext() && ErrorRecovery)
+      createImplicitModuleImport(Correction.getCorrectionRange().getBegin(),
+                                 Owner);
+    return;
+  }
+
   Diag(Correction.getCorrectionRange().getBegin(), TypoDiag)
     << CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint());
 

Modified: cfe/trunk/test/Modules/auto-module-import.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/auto-module-import.m?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/test/Modules/auto-module-import.m (original)
+++ cfe/trunk/test/Modules/auto-module-import.m Tue Aug 20 15:35:18 2013
@@ -1,10 +1,12 @@
 // RUN: rm -rf %t
+// RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -F %S/Inputs %s -verify -DERRORS
 // RUN: %clang_cc1 -Wauto-import -fmodules-cache-path=%t -fmodules -F %S/Inputs %s -verify
+// 
+// Test both with and without the declarations that refer to unimported
+// entities. For error recovery, those cases implicitly trigger an import.
 
 #include <DependsOnModule/DependsOnModule.h> // expected-warning{{treating #include as an import of module 'DependsOnModule'}}
 
-// expected-note at Inputs/NoUmbrella.framework/PrivateHeaders/A_Private.h:1{{'no_umbrella_A_private' declared here}}
-
 #ifdef MODULE_H_MACRO
 #  error MODULE_H_MACRO should have been hidden
 #endif
@@ -13,15 +15,21 @@
 #  error DEPENDS_ON_MODULE should have been hidden
 #endif
 
-Module *mod; // expected-error{{unknown type name 'Module'}}
-
+#ifdef ERRORS
+Module *mod; // expected-error{{declaration of 'Module' must be imported from module 'Module' before it is required}}
+// expected-note at Inputs/Module.framework/Headers/Module.h:15 {{previous}}
+#else
 #import <AlsoDependsOnModule/AlsoDependsOnModule.h> // expected-warning{{treating #import as an import of module 'AlsoDependsOnModule'}}
+#endif
 Module *mod2;
 
 int getDependsOther() { return depends_on_module_other; }
 
 void testSubframeworkOther() {
-  double *sfo1 = sub_framework_other; // expected-error{{use of undeclared identifier 'sub_framework_other'}}
+#ifdef ERRORS
+  double *sfo1 = sub_framework_other; // expected-error{{declaration of 'sub_framework_other' must be imported from module 'DependsOnModule.SubFramework.Other'}}
+  // expected-note at Inputs/DependsOnModule.framework/Frameworks/SubFramework.framework/Headers/Other.h:15 {{previous}}
+#endif
 }
 
 // Test umbrella-less submodule includes
@@ -32,8 +40,10 @@ int getNoUmbrellaA() { return no_umbrell
 #include <NoUmbrella/SubDir/C.h> // expected-warning{{treating #include as an import of module 'NoUmbrella.SubDir.C'}}
 int getNoUmbrellaC() { return no_umbrella_C; } 
 
+#ifndef ERRORS
 // Test header cross-subframework include pattern.
 #include <DependsOnModule/../Frameworks/SubFramework.framework/Headers/Other.h> // expected-warning{{treating #include as an import of module 'DependsOnModule.SubFramework.Other'}}
+#endif
 
 void testSubframeworkOtherAgain() {
   double *sfo1 = sub_framework_other;
@@ -61,7 +71,8 @@ int getModulePrivate() { return module_p
 #include <NoUmbrella/A_Private.h> // expected-warning{{treating #include as an import of module 'NoUmbrella.Private.A_Private'}}
 int getNoUmbrellaAPrivate() { return no_umbrella_A_private; }
 
-int getNoUmbrellaBPrivateFail() { return no_umbrella_B_private; } // expected-error{{use of undeclared identifier 'no_umbrella_B_private'; did you mean 'no_umbrella_A_private'?}}
+int getNoUmbrellaBPrivateFail() { return no_umbrella_B_private; } // expected-error{{declaration of 'no_umbrella_B_private' must be imported from module 'NoUmbrella.Private.B_Private'}}
+// expected-note at Inputs/NoUmbrella.framework/PrivateHeaders/B_Private.h:1 {{previous}}
 
 // Test inclusion of headers that are under an umbrella directory but
 // not actually part of the module.

Modified: cfe/trunk/test/Modules/decldef.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/decldef.m?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/test/Modules/decldef.m (original)
+++ cfe/trunk/test/Modules/decldef.m Tue Aug 20 15:35:18 2013
@@ -1,13 +1,16 @@
 // RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_EARLY
 // RUN: %clang_cc1 -fmodules -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify
 
-// expected-note at Inputs/def.h:5 {{previous definition is here}}
+// expected-note at Inputs/def.h:5 {{previous}}
 
 @class Def;
 Def *def;
 
 @import decldef;
-A *a1; // expected-error{{unknown type name 'A'}}
+#ifdef USE_EARLY
+A *a1; // expected-error{{declaration of 'A' must be imported from module 'decldef.Def' before it is required}}
+#endif
 B *b1; // expected-error{{must use 'struct' tag to refer to type 'B'}}
 @import decldef.Decl;
 
@@ -15,7 +18,10 @@ A *a2;
 struct B *b;
 
 void testA(A *a) {
-  a->ivar = 17; // expected-error{{definition of 'A' must be imported from module 'decldef.Def' before it is required}}
+  a->ivar = 17;
+#ifndef USE_EARLY
+  // expected-error at -2{{definition of 'A' must be imported from module 'decldef.Def' before it is required}}
+#endif
 }
 
 void testB() {

Modified: cfe/trunk/test/Modules/decldef.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/decldef.mm?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/test/Modules/decldef.mm (original)
+++ cfe/trunk/test/Modules/decldef.mm Tue Aug 20 15:35:18 2013
@@ -1,7 +1,8 @@
 // RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify -DUSE_EARLY
 // RUN: %clang_cc1 -fmodules -fobjc-arc -I %S/Inputs -fmodules-cache-path=%t %s -verify
 
-// expected-note at Inputs/def.h:5 {{previous definition is here}}
+// expected-note at Inputs/def.h:5 {{previous}}
 
 @class Def;
 Def *def;
@@ -13,15 +14,20 @@ Def2 *def2;
 @end
 
 @import decldef;
-A *a1; // expected-error{{unknown type name 'A'}}
-B *b1; // expected-error{{unknown type name 'B'}}
+#ifdef USE_EARLY
+A *a1; // expected-error{{declaration of 'A' must be imported from module 'decldef.Def'}}
+B *b1;
+#endif
 @import decldef.Decl;
 
 A *a2;
 B *b;
 
 void testA(A *a) {
-  a->ivar = 17; // expected-error{{definition of 'A' must be imported from module 'decldef.Def' before it is required}}
+  a->ivar = 17;
+#ifndef USE_EARLY
+  // expected-error at -2{{definition of 'A' must be imported from module 'decldef.Def' before it is required}}
+#endif
 }
 
 void testB() {

Modified: cfe/trunk/test/Modules/normal-module-map.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/normal-module-map.cpp?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/test/Modules/normal-module-map.cpp (original)
+++ cfe/trunk/test/Modules/normal-module-map.cpp Tue Aug 20 15:35:18 2013
@@ -24,8 +24,8 @@ int testNestedUmbrellaA() {
 
 int testNestedUmbrellaBFail() {
   return nested_umbrella_b;
-  // expected-error at -1{{use of undeclared identifier 'nested_umbrella_b'; did you mean 'nested_umbrella_a'?}}
-  // expected-note at Inputs/normal-module-map/nested_umbrella/a.h:1{{'nested_umbrella_a' declared here}}
+  // expected-error at -1{{declaration of 'nested_umbrella_b' must be imported from module 'nested_umbrella.b' before it is required}}
+  // expected-note at Inputs/normal-module-map/nested_umbrella/b.h:1{{previous}}
 }
 
 @import nested_umbrella.b;

Modified: cfe/trunk/test/Modules/subframeworks.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/subframeworks.m?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/test/Modules/subframeworks.m (original)
+++ cfe/trunk/test/Modules/subframeworks.m Tue Aug 20 15:35:18 2013
@@ -5,7 +5,8 @@
 @import DependsOnModule;
 
 void testSubFramework() {
-  float *sf1 = sub_framework; // expected-error{{use of undeclared identifier 'sub_framework'}}
+  float *sf1 = sub_framework; // expected-error{{declaration of 'sub_framework' must be imported from module 'DependsOnModule.SubFramework' before it is required}}
+  // expected-note at Inputs/DependsOnModule.framework/Frameworks/SubFramework.framework/Headers/SubFramework.h:2 {{previous}}
 }
 
 @import DependsOnModule.SubFramework;

Modified: cfe/trunk/test/Modules/submodules.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/submodules.cpp?rev=188821&r1=188820&r2=188821&view=diff
==============================================================================
--- cfe/trunk/test/Modules/submodules.cpp (original)
+++ cfe/trunk/test/Modules/submodules.cpp Tue Aug 20 15:35:18 2013
@@ -7,8 +7,9 @@
 vector<int> vi;
 
 // Note: remove_reference is not visible yet.
-remove_reference<int&>::type *int_ptr = 0; // expected-error{{unknown type name 'remove_reference'}} \
-// expected-error{{expected unqualified-id}}
+remove_reference<int&>::type *int_ptr = 0; // expected-error{{declaration of 'remove_reference' must be imported from module 'std.type_traits' before it is required}}
+// expected-note at Inputs/submodules/type_traits.h:2{{previous}}
+// expected-note at Inputs/submodules/hash_map.h:1{{previous}}
 
 @import std.typetraits; // expected-error{{no submodule named 'typetraits' in module 'std'; did you mean 'type_traits'?}}
 
@@ -20,8 +21,7 @@ remove_reference<int&>::type *int_ptr2 =
 @import std; // import everything in 'std'
 
 // hash_map still isn't available.
-hash_map<int, float> ints_to_floats; // expected-error{{unknown type name 'hash_map'}} \
-// expected-error{{expected unqualified-id}}
+hash_map<int, float> ints_to_floats; // expected-error{{declaration of 'hash_map' must be imported from module 'std.hash_map' before it is required}}
 
 @import std.hash_map;
 





More information about the cfe-commits mailing list