diff options
| -rw-r--r-- | clang/include/clang/AST/DeclCXX.h | 23 | ||||
| -rw-r--r-- | clang/lib/AST/Decl.cpp | 17 | ||||
| -rw-r--r-- | clang/lib/AST/DeclCXX.cpp | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 3 | ||||
| -rw-r--r-- | clang/test/SemaCXX/undefined-internal.cpp | 7 | 
5 files changed, 40 insertions, 16 deletions
diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index eb6035680b9..ab6fcba4d7e 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -2352,22 +2352,27 @@ public:  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 @@ public:    /// \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/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index cb375eb4e26..a431c5317e0 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -476,6 +476,13 @@ template <typename T> static bool isInExternCContext(T *D) {    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 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D,          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 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition(    //   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/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp index c2b751316e9..064649904d3 100644 --- a/clang/lib/AST/DeclCXX.cpp +++ b/clang/lib/AST/DeclCXX.cpp @@ -1816,14 +1816,14 @@ LinkageSpecDecl *LinkageSpecDecl::Create(ASTContext &C,                                           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/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b5fb85856c8..5f0908ae933 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -10507,7 +10507,8 @@ Decl *Sema::ActOnStartLinkageSpecification(Scope *S, SourceLocation ExternLoc,    // 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/clang/test/SemaCXX/undefined-internal.cpp b/clang/test/SemaCXX/undefined-internal.cpp index 839fdafb341..1b76a86dcb5 100644 --- a/clang/test/SemaCXX/undefined-internal.cpp +++ b/clang/test/SemaCXX/undefined-internal.cpp @@ -323,3 +323,10 @@ namespace test13 {    }  } +namespace test14 { +  extern "C" const int foo; + +  int f() { +    return foo; +  } +}  | 

