Add r180263 back, but fix hasBraces() to be correct during parsing.

Original commit message:

Fix a case in linkage computation that should check for single line extern "C".

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180591 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h
index eb60356..ab6fcba 100644
--- a/include/clang/AST/DeclCXX.h
+++ b/include/clang/AST/DeclCXX.h
@@ -2352,22 +2352,27 @@
 private:
   /// Language - The language for this linkage specification.
   LanguageIDs Language;
+  /// True if this linkage spec has brances. This is needed so that hasBraces()
+  /// returns the correct result while the linkage spec body is being parsed.
+  /// Once RBraceLoc has been set this is not used, so it doesn't need to be
+  /// serialized.
+  bool HasBraces;
   /// ExternLoc - The source location for the extern keyword.
   SourceLocation ExternLoc;
   /// RBraceLoc - The source location for the right brace (if valid).
   SourceLocation RBraceLoc;
 
   LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc,
-                  SourceLocation LangLoc, LanguageIDs lang,
-                  SourceLocation RBLoc)
+                  SourceLocation LangLoc, LanguageIDs lang, bool HasBraces)
     : Decl(LinkageSpec, DC, LangLoc), DeclContext(LinkageSpec),
-      Language(lang), ExternLoc(ExternLoc), RBraceLoc(RBLoc) { }
+      Language(lang), HasBraces(HasBraces), ExternLoc(ExternLoc),
+      RBraceLoc(SourceLocation()) { }
 
 public:
   static LinkageSpecDecl *Create(ASTContext &C, DeclContext *DC,
                                  SourceLocation ExternLoc,
                                  SourceLocation LangLoc, LanguageIDs Lang,
-                                 SourceLocation RBraceLoc = SourceLocation());
+                                 bool HasBraces);
   static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID);
   
   /// \brief Return the language specified by this linkage specification.
@@ -2377,12 +2382,18 @@
 
   /// \brief Determines whether this linkage specification had braces in
   /// its syntactic form.
-  bool hasBraces() const { return RBraceLoc.isValid(); }
+  bool hasBraces() const {
+    assert(!RBraceLoc.isValid() || HasBraces);
+    return HasBraces;
+  }
 
   SourceLocation getExternLoc() const { return ExternLoc; }
   SourceLocation getRBraceLoc() const { return RBraceLoc; }
   void setExternLoc(SourceLocation L) { ExternLoc = L; }
-  void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
+  void setRBraceLoc(SourceLocation L) {
+    RBraceLoc = L;
+    HasBraces = RBraceLoc.isValid();
+  }
 
   SourceLocation getLocEnd() const LLVM_READONLY {
     if (hasBraces())
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index cb375eb..a431c53 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -476,6 +476,13 @@
   return First->getDeclContext()->isExternCContext();
 }
 
+static bool isSingleLineExternC(const Decl &D) {
+  if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext()))
+    if (SD->getLanguage() == LinkageSpecDecl::lang_c && !SD->hasBraces())
+      return true;
+  return false;
+}
+
 static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,
                                               LVComputationKind computation) {
   assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
@@ -504,7 +511,8 @@
         return PrevVar->getLinkageAndVisibility();
 
       if (Var->getStorageClass() != SC_Extern &&
-          Var->getStorageClass() != SC_PrivateExtern)
+          Var->getStorageClass() != SC_PrivateExtern &&
+          !isSingleLineExternC(*Var))
         return LinkageInfo::internal();
     }
 
@@ -1580,11 +1588,8 @@
   //   A declaration directly contained in a linkage-specification is treated
   //   as if it contains the extern specifier for the purpose of determining
   //   the linkage of the declared name and whether it is a definition.
-  const DeclContext *DC = getDeclContext();
-  if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(DC)) {
-    if (SD->getLanguage() == LinkageSpecDecl::lang_c && !SD->hasBraces())
-      return DeclarationOnly;
-  }
+  if (isSingleLineExternC(*this))
+    return DeclarationOnly;
 
   // C99 6.9.2p2:
   //   A declaration of an object that has file scope without an initializer,
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index c2b7513..0646499 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -1816,14 +1816,14 @@
                                          SourceLocation ExternLoc,
                                          SourceLocation LangLoc,
                                          LanguageIDs Lang,
-                                         SourceLocation RBraceLoc) {
-  return new (C) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, RBraceLoc);
+                                         bool HasBraces) {
+  return new (C) LinkageSpecDecl(DC, ExternLoc, LangLoc, Lang, HasBraces);
 }
 
 LinkageSpecDecl *LinkageSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
   void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LinkageSpecDecl));
   return new (Mem) LinkageSpecDecl(0, SourceLocation(), SourceLocation(),
-                                   lang_c, SourceLocation());
+                                   lang_c, false);
 }
 
 void UsingDirectiveDecl::anchor() { }
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index b5fb858..5f0908a 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -10507,7 +10507,8 @@
   // FIXME: Add all the various semantics of linkage specifications
 
   LinkageSpecDecl *D = LinkageSpecDecl::Create(Context, CurContext,
-                                               ExternLoc, LangLoc, Language);
+                                               ExternLoc, LangLoc, Language,
+                                               LBraceLoc.isValid());
   CurContext->addDecl(D);
   PushDeclContext(S, D);
   return D;
diff --git a/test/SemaCXX/undefined-internal.cpp b/test/SemaCXX/undefined-internal.cpp
index 839fdaf..1b76a86 100644
--- a/test/SemaCXX/undefined-internal.cpp
+++ b/test/SemaCXX/undefined-internal.cpp
@@ -323,3 +323,10 @@
   }
 }
 
+namespace test14 {
+  extern "C" const int foo;
+
+  int f() {
+    return foo;
+  }
+}