Rework the way we find locally-scoped external declarations when we
need them to evaluate redeclarations or call a function that hasn't
already been declared. We now keep a DenseMap of these locally-scoped
declarations so that they are not visible but can be quickly found,
e.g., when we're looking for previous declarations or before we go
ahead and implicitly declare a function that's being called. Fixes
PR3672.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@65792 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index b30b869..1ebfbf7 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -63,6 +63,28 @@
   return getType();
 }
 
+bool VarDecl::isExternC(ASTContext &Context) const {
+  if (!Context.getLangOptions().CPlusPlus)
+    return (getDeclContext()->isTranslationUnit() && 
+            getStorageClass() != Static) ||
+      (getDeclContext()->isFunctionOrMethod() && hasExternalStorage());
+
+  for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 
+       DC = DC->getParent()) {
+    if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
+      if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
+        return getStorageClass() != Static;
+
+      break;
+    }
+
+    if (DC->isFunctionOrMethod())
+      return false;
+  }
+
+  return false;
+}
+
 OriginalParmVarDecl *OriginalParmVarDecl::Create(
                                  ASTContext &C, DeclContext *DC,
                                  SourceLocation L, IdentifierInfo *Id,
@@ -273,6 +295,25 @@
     getIdentifier() && getIdentifier()->isStr("main");
 }
 
+bool FunctionDecl::isExternC(ASTContext &Context) const {
+  // In C, any non-static, non-overloadable function has external
+  // linkage.
+  if (!Context.getLangOptions().CPlusPlus)
+    return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+
+  for (const DeclContext *DC = getDeclContext(); !DC->isTranslationUnit(); 
+       DC = DC->getParent()) {
+    if (const LinkageSpecDecl *Linkage = dyn_cast<LinkageSpecDecl>(DC))  {
+      if (Linkage->getLanguage() == LinkageSpecDecl::lang_c)
+        return getStorageClass() != Static && !getAttr<OverloadableAttr>();
+
+      break;
+    }
+  }
+
+  return false;
+}
+
 /// \brief Returns a value indicating whether this function
 /// corresponds to a builtin function.
 ///