<div dir="ltr">I know, I yelled at him in person yesterday.  :)  He said the logic should probably be disabled for -fms-compatibility.  But I'm OK with letting him fix that and roll it back in.</div><div class="gmail_extra">
<br><br><div class="gmail_quote">On Sat, Jun 29, 2013 at 1:36 AM, Timur Iskhodzhanov <span dir="ltr"><<a href="mailto:timurrrr@google.com" target="_blank">timurrrr@google.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi Richard,<br>
<br>
This has broken compilation of <windows.h>:<br>
<br>
C:\Program Files (x86)\Microsoft Visual Studio<br>
10.0\VC\INCLUDE\stdio.h:276:47: error: declaration of 'gets_s' in<br>
<div class="im">global scope conflicts with declaration with C language linkage<br>
</div>__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_0(char *, gets_s, char, _Buffer)<br>
                                              ^<br>
C:\Program Files (x86)\Microsoft Visual Studio<br>
10.0\VC\INCLUDE\crtdefs.h:587:27: note: expanded from macro<br>
'__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_0'<br>
    _ReturnType __CRTDECL _FuncName(_DstType (&_Dst)[_Size])<br>
_CRT_SECURE_CPP_NOTHROW \<br>
                          ^<br>
C:\Program Files (x86)\Microsoft Visual Studio<br>
10.0\VC\INCLUDE\stdio.h:274:24: note: declared with C language linkage<br>
here<br>
_CRTIMP char * __cdecl gets_s(_Out_z_cap_(_Size) char * _Buf, _In_<br>
rsize_t _Size);<br>
                       ^<br>
C:\Program Files (x86)\Microsoft Visual Studio<br>
10.0\VC\INCLUDE\stdio.h:319:52: error: declaration of '_snprintf_s' in<br>
<div class="im">global scope conflicts with declaration with C language linkage<br>
</div>__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_2_ARGLIST(int, _snprintf_s,<br>
_vsnprintf_s, _Deref_post_z_ char, _Dest, _In_ size_t, _MaxCount,<br>
_In_z_ _Printf_format_string_ const char *,_Format)<br>
                                                   ^<br>
C:\Program Files (x86)\Microsoft Visual Studio<br>
10.0\VC\INCLUDE\crtdefs.h:704:27: note: expanded from macro<br>
'__DEFINE_CPP_OVERLOAD_SECURE_FUNC_0_2_ARGLIST'<br>
    _ReturnType __CRTDECL _FuncName(_DstType (&_Dst)[_Size], _TType1<br>
_TArg1, _TType2 _TArg2, ...) _CRT_SECURE_CPP_NOTHROW \<br>
                          ^<br>
C:\Program Files (x86)\Microsoft Visual Studio<br>
10.0\VC\INCLUDE\stdio.h:318:52: note: declared with C language linkage<br>
here<br>
_Check_return_opt_ _CRTIMP_ALTERNATIVE int __cdecl<br>
_snprintf_s(_Out_z_bytecap_(_SizeInBytes) char * _DstBuf, _In_ size_t<br>
_SizeInBytes, _In_ size_t _MaxCount, _In_z_ _Printf_format_string_<br>
const char * _Format, ...);<br>
---<br>
<br>
I'm going to revert your change to make the bots greener over the weekend.<br>
Please investigate how extern "C" is used here and add tests to<br>
prevent new regressions.<br>
<br>
--<br>
Timur<br>
<br>
2013/6/29 Richard Smith <<a href="mailto:richard-llvm@metafoo.co.uk">richard-llvm@metafoo.co.uk</a>>:<br>
<div class="HOEnZb"><div class="h5">> Author: rsmith<br>
> Date: Fri Jun 28 17:03:51 2013<br>
> New Revision: 185229<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=185229&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=185229&view=rev</a><br>
> Log:<br>
> PR7927, PR16247: Reimplement handling of matching extern "C" declarations<br>
> across scopes.<br>
><br>
> When we declare an extern "C" name that is not a redeclaration of an entity in<br>
> the same scope, check whether it redeclares some extern "C" entity from another<br>
> scope, and if not, check whether it conflicts with a (non-extern-"C") entity in<br>
> the translation unit.<br>
><br>
> When we declare a name in the translation unit that is not a redeclaration,<br>
> check whether it conflicts with any extern "C" entities (possibly from other<br>
> scopes).<br>
><br>
> Modified:<br>
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
>     cfe/trunk/lib/Sema/SemaDecl.cpp<br>
>     cfe/trunk/lib/Sema/SemaOverload.cpp<br>
>     cfe/trunk/test/CXX/class.access/class.friend/p1.cpp<br>
>     cfe/trunk/test/Sema/overloadable.c<br>
>     cfe/trunk/test/SemaCXX/extern-c.cpp<br>
>     cfe/trunk/test/SemaCXX/friend.cpp<br>
>     cfe/trunk/test/SemaCXX/linkage-spec.cpp<br>
>     cfe/trunk/test/SemaCXX/linkage2.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Jun 28 17:03:51 2013<br>
> @@ -3493,6 +3493,11 @@ def err_static_non_static : Error<<br>
>    "static declaration of %0 follows non-static declaration">;<br>
>  def err_different_language_linkage : Error<<br>
>    "declaration of %0 has a different language linkage">;<br>
> +def err_extern_c_global_conflict : Error<<br>
> +  "declaration of %1 %select{with C language linkage|in global scope}0 "<br>
> +  "conflicts with declaration %select{in global scope|with C language linkage}0">;<br>
> +def note_extern_c_global_conflict : Note<<br>
> +  "declared %select{in global scope|with C language linkage}0 here">;<br>
>  def warn_weak_import : Warning <<br>
>    "an already-declared variable is made a weak_import declaration %0">;<br>
>  def warn_static_non_static : ExtWarn<<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jun 28 17:03:51 2013<br>
> @@ -4359,10 +4359,14 @@ TryToFixInvalidVariablyModifiedTypeSourc<br>
>  /// function-scope declarations.<br>
>  void<br>
>  Sema::RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S) {<br>
> -  assert(<br>
> -      !ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit() &&<br>
> -      "Decl is not a locally-scoped decl!");<br>
> +  if (!getLangOpts().CPlusPlus &&<br>
> +      ND->getLexicalDeclContext()->getRedeclContext()->isTranslationUnit())<br>
> +    // Don't need to track declarations in the TU in C.<br>
> +    return;<br>
> +<br>
>    // Note that we have a locally-scoped external with this name.<br>
> +  // FIXME: There can be multiple such declarations if they are functions marked<br>
> +  // __attribute__((overloadable)) declared in function scope in C.<br>
>    LocallyScopedExternCDecls[ND->getDeclName()] = ND;<br>
>  }<br>
><br>
> @@ -4681,6 +4685,32 @@ static bool isFunctionDefinitionDiscarde<br>
>    return isC99Inline;<br>
>  }<br>
><br>
> +/// Determine whether a variable is extern "C" prior to attaching<br>
> +/// an initializer. We can't just call isExternC() here, because that<br>
> +/// will also compute and cache whether the declaration is externally<br>
> +/// visible, which might change when we attach the initializer.<br>
> +///<br>
> +/// This can only be used if the declaration is known to not be a<br>
> +/// redeclaration of an internal linkage declaration.<br>
> +///<br>
> +/// For instance:<br>
> +///<br>
> +///   auto x = []{};<br>
> +///<br>
> +/// Attaching the initializer here makes this declaration not externally<br>
> +/// visible, because its type has internal linkage.<br>
> +///<br>
> +/// FIXME: This is a hack.<br>
> +template<typename T><br>
> +static bool isIncompleteDeclExternC(Sema &S, const T *D) {<br>
> +  if (S.getLangOpts().CPlusPlus) {<br>
> +    // In C++, the overloadable attribute negates the effects of extern "C".<br>
> +    if (!D->isInExternCContext() || D->template hasAttr<OverloadableAttr>())<br>
> +      return false;<br>
> +  }<br>
> +  return D->isExternC();<br>
> +}<br>
> +<br>
>  static bool shouldConsiderLinkage(const VarDecl *VD) {<br>
>    const DeclContext *DC = VD->getDeclContext()->getRedeclContext();<br>
>    if (DC->isFunctionOrMethod())<br>
> @@ -5070,16 +5100,10 @@ Sema::ActOnVariableDeclarator(Scope *S,<br>
>    ProcessPragmaWeak(S, NewVD);<br>
>    checkAttributesAfterMerging(*this, *NewVD);<br>
><br>
> -  // If this is the first declaration of an extern C variable that is not<br>
> -  // declared directly in the translation unit, update the map of such<br>
> -  // variables.<br>
> -  if (!CurContext->getRedeclContext()->isTranslationUnit() &&<br>
> -      !NewVD->getPreviousDecl() && !NewVD->isInvalidDecl() &&<br>
> -      // FIXME: We only check isExternC if we're in an extern C context,<br>
> -      // to avoid computing and caching an 'externally visible' flag which<br>
> -      // could change if the variable's type is not visible.<br>
> -      (!getLangOpts().CPlusPlus || NewVD->isInExternCContext()) &&<br>
> -      NewVD->isExternC())<br>
> +  // If this is the first declaration of an extern C variable, update<br>
> +  // the map of such variables.<br>
> +  if (!NewVD->getPreviousDecl() && !NewVD->isInvalidDecl() &&<br>
> +      isIncompleteDeclExternC(*this, NewVD))<br>
>      RegisterLocallyScopedExternCDecl(NewVD, S);<br>
><br>
>    return NewVD;<br>
> @@ -5180,30 +5204,120 @@ void Sema::CheckShadow(Scope *S, VarDecl<br>
>    CheckShadow(S, D, R);<br>
>  }<br>
><br>
> +/// Check for conflict between this global or extern "C" declaration and<br>
> +/// previous global or extern "C" declarations. This is only used in C++.<br>
>  template<typename T><br>
> -static bool mayConflictWithNonVisibleExternC(const T *ND) {<br>
> -  const DeclContext *DC = ND->getDeclContext();<br>
> -  if (DC->getRedeclContext()->isTranslationUnit())<br>
> -    return true;<br>
> +static bool checkGlobalOrExternCConflict(<br>
> +    Sema &S, const T *ND, bool IsGlobal, LookupResult &Previous) {<br>
> +  assert(S.getLangOpts().CPlusPlus && "only C++ has extern \"C\"");<br>
> +  NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName());<br>
> +<br>
> +  if (!Prev && IsGlobal && !isIncompleteDeclExternC(S, ND)) {<br>
> +    // The common case: this global doesn't conflict with any extern "C"<br>
> +    // declaration.<br>
> +    return false;<br>
> +  }<br>
><br>
> -  // We know that is the first decl we see, other than function local<br>
> -  // extern C ones. If this is C++ and the decl is not in a extern C context<br>
> -  // it cannot have C language linkage. Avoid calling isExternC in that case.<br>
> -  // We need to this because of code like<br>
> -  //<br>
> -  // namespace { struct bar {}; }<br>
> -  // auto foo = bar();<br>
> -  //<br>
> -  // This code runs before the init of foo is set, and therefore before<br>
> -  // the type of foo is known. Not knowing the type we cannot know its linkage<br>
> -  // unless it is in an extern C block.<br>
> -  if (!ND->isInExternCContext()) {<br>
> -    const ASTContext &Context = ND->getASTContext();<br>
> -    if (Context.getLangOpts().CPlusPlus)<br>
> +  if (Prev) {<br>
> +    if (!IsGlobal || isIncompleteDeclExternC(S, ND)) {<br>
> +      // Both the old and new declarations have C language linkage. This is a<br>
> +      // redeclaration.<br>
> +      Previous.clear();<br>
> +      Previous.addDecl(Prev);<br>
> +      return true;<br>
> +    }<br>
> +<br>
> +    // This is a global, non-extern "C" declaration, and there is a previous<br>
> +    // non-global extern "C" declaration. Diagnose.<br>
> +  } else {<br>
> +    // The declaration is extern "C". Check for any declaration in the<br>
> +    // translation unit which might conflict.<br>
> +    if (IsGlobal) {<br>
> +      // We have already performed the lookup into the translation unit.<br>
> +      IsGlobal = false;<br>
> +      for (LookupResult::iterator I = Previous.begin(), E = Previous.end();<br>
> +           I != E; ++I) {<br>
> +        if (isa<VarDecl>(*I) || isa<FunctionDecl>(*I)) {<br>
> +          Prev = *I;<br>
> +          break;<br>
> +        }<br>
> +      }<br>
> +    } else {<br>
> +      DeclContext::lookup_result R =<br>
> +          S.Context.getTranslationUnitDecl()->lookup(ND->getDeclName());<br>
> +      for (DeclContext::lookup_result::iterator I = R.begin(), E = R.end();<br>
> +           I != E; ++I) {<br>
> +        if (isa<VarDecl>(*I) || isa<FunctionDecl>(*I)) {<br>
> +          Prev = *I;<br>
> +          break;<br>
> +        }<br>
> +        // FIXME: If we have any other entity with this name in global scope,<br>
> +        // the declaration is ill-formed, but that is a defect: it breaks the<br>
> +        // 'stat' hack, for instance.<br>
> +      }<br>
> +    }<br>
> +<br>
> +    if (!Prev)<br>
>        return false;<br>
>    }<br>
><br>
> -  return ND->isExternC();<br>
> +  // Use the first declaration's location to ensure we point at something which<br>
> +  // is lexically inside an extern "C" linkage-spec.<br>
> +  assert(Prev && "should have found a previous declaration to diagnose");<br>
> +  if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Prev))<br>
> +    Prev = FD->getFirstDeclaration();<br>
> +  else<br>
> +    Prev = cast<VarDecl>(Prev)->getFirstDeclaration();<br>
> +<br>
> +  S.Diag(ND->getLocation(), diag::err_extern_c_global_conflict)<br>
> +    << IsGlobal << ND;<br>
> +  S.Diag(Prev->getLocation(), diag::note_extern_c_global_conflict)<br>
> +    << IsGlobal;<br>
> +  return false;<br>
> +}<br>
> +<br>
> +/// Apply special rules for handling extern "C" declarations. Returns \c true<br>
> +/// if we have found that this is a redeclaration of some prior entity.<br>
> +///<br>
> +/// Per C++ [dcl.link]p6:<br>
> +///   Two declarations [for a function or variable] with C language linkage<br>
> +///   with the same name that appear in different scopes refer to the same<br>
> +///   [entity]. An entity with C language linkage shall not be declared with<br>
> +///   the same name as an entity in global scope.<br>
> +template<typename T><br>
> +static bool checkForConflictWithNonVisibleExternC(Sema &S, const T *ND,<br>
> +                                                  LookupResult &Previous) {<br>
> +  if (!S.getLangOpts().CPlusPlus) {<br>
> +    // In C, when declaring a global variable, look for a corresponding 'extern'<br>
> +    // variable declared in function scope.<br>
> +    //<br>
> +    // FIXME: The corresponding case in C++ does not work.  We should instead<br>
> +    // set the semantic DC for an extern local variable to be the innermost<br>
> +    // enclosing namespace, and ensure they are only found by redeclaration<br>
> +    // lookup.<br>
> +    if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit()) {<br>
> +      if (NamedDecl *Prev = S.findLocallyScopedExternCDecl(ND->getDeclName())) {<br>
> +        Previous.clear();<br>
> +        Previous.addDecl(Prev);<br>
> +        return true;<br>
> +      }<br>
> +    }<br>
> +    return false;<br>
> +  }<br>
> +<br>
> +  // A declaration in the translation unit can conflict with an extern "C"<br>
> +  // declaration.<br>
> +  if (ND->getDeclContext()->getRedeclContext()->isTranslationUnit())<br>
> +    return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/true, Previous);<br>
> +<br>
> +  // An extern "C" declaration can conflict with a declaration in the<br>
> +  // translation unit or can be a redeclaration of an extern "C" declaration<br>
> +  // in another scope.<br>
> +  if (isIncompleteDeclExternC(S,ND))<br>
> +    return checkGlobalOrExternCConflict(S, ND, /*IsGlobal*/false, Previous);<br>
> +<br>
> +  // Neither global nor extern "C": nothing to do.<br>
> +  return false;<br>
>  }<br>
><br>
>  void Sema::CheckVariableDeclarationType(VarDecl *NewVD) {<br>
> @@ -5386,14 +5500,9 @@ bool Sema::CheckVariableDeclaration(VarD<br>
>    // The most important point here is that we're not allowed to<br>
>    // update our understanding of the type according to declarations<br>
>    // not in scope.<br>
> -  bool PreviousWasHidden = false;<br>
> -  if (Previous.empty() && mayConflictWithNonVisibleExternC(NewVD)) {<br>
> -    if (NamedDecl *ExternCPrev =<br>
> -            findLocallyScopedExternCDecl(NewVD->getDeclName())) {<br>
> -      Previous.addDecl(ExternCPrev);<br>
> -      PreviousWasHidden = true;<br>
> -    }<br>
> -  }<br>
> +  bool PreviousWasHidden =<br>
> +      Previous.empty() &&<br>
> +      checkForConflictWithNonVisibleExternC(*this, NewVD, Previous);<br>
><br>
>    // Filter out any non-conflicting previous declarations.<br>
>    filterNonConflictingPreviousDecls(Context, NewVD, Previous);<br>
> @@ -6625,12 +6734,10 @@ Sema::ActOnFunctionDeclarator(Scope *S,<br>
>    // marking the function.<br>
>    AddCFAuditedAttribute(NewFD);<br>
><br>
> -  // If this is the first declaration of an extern C variable that is not<br>
> -  // declared directly in the translation unit, update the map of such<br>
> -  // variables.<br>
> -  if (!CurContext->getRedeclContext()->isTranslationUnit() &&<br>
> -      !NewFD->getPreviousDecl() && NewFD->isExternC() &&<br>
> -      !NewFD->isInvalidDecl())<br>
> +  // If this is the first declaration of an extern C variable, update<br>
> +  // the map of such variables.<br>
> +  if (!NewFD->getPreviousDecl() && !NewFD->isInvalidDecl() &&<br>
> +      isIncompleteDeclExternC(*this, NewFD))<br>
>      RegisterLocallyScopedExternCDecl(NewFD, S);<br>
><br>
>    // Set this FunctionDecl's range up to the right paren.<br>
> @@ -6734,15 +6841,6 @@ bool Sema::CheckFunctionDeclaration(Scop<br>
>    assert(!NewFD->getResultType()->isVariablyModifiedType()<br>
>           && "Variably modified return types are not handled here");<br>
><br>
> -  // Check for a previous declaration of this name.<br>
> -  if (Previous.empty() && mayConflictWithNonVisibleExternC(NewFD)) {<br>
> -    // Since we did not find anything by this name, look for a non-visible<br>
> -    // extern "C" declaration with the same name.<br>
> -    if (NamedDecl *ExternCPrev =<br>
> -            findLocallyScopedExternCDecl(NewFD->getDeclName()))<br>
> -      Previous.addDecl(ExternCPrev);<br>
> -  }<br>
> -<br>
>    // Filter out any non-conflicting previous declarations.<br>
>    filterNonConflictingPreviousDecls(Context, NewFD, Previous);<br>
><br>
> @@ -6796,6 +6894,34 @@ bool Sema::CheckFunctionDeclaration(Scop<br>
>        }<br>
>      }<br>
>    }<br>
> +<br>
> +  // Check for a previous extern "C" declaration with this name.<br>
> +  if (!Redeclaration &&<br>
> +      checkForConflictWithNonVisibleExternC(*this, NewFD, Previous)) {<br>
> +    filterNonConflictingPreviousDecls(Context, NewFD, Previous);<br>
> +    if (!Previous.empty()) {<br>
> +      // This is an extern "C" declaration with the same name as a previous<br>
> +      // declaration, and thus redeclares that entity...<br>
> +      Redeclaration = true;<br>
> +      OldDecl = Previous.getFoundDecl();<br>
> +<br>
> +      // ... except in the presence of __attribute__((overloadable)).<br>
> +      if (OldDecl->hasAttr<OverloadableAttr>()) {<br>
> +        if (!getLangOpts().CPlusPlus && !NewFD->hasAttr<OverloadableAttr>()) {<br>
> +          Diag(NewFD->getLocation(), diag::err_attribute_overloadable_missing)<br>
> +            << Redeclaration << NewFD;<br>
> +          Diag(Previous.getFoundDecl()->getLocation(),<br>
> +               diag::note_attribute_overloadable_prev_overload);<br>
> +          NewFD->addAttr(::new (Context) OverloadableAttr(SourceLocation(),<br>
> +                                                          Context));<br>
> +        }<br>
> +        if (IsOverload(NewFD, cast<FunctionDecl>(OldDecl), false)) {<br>
> +          Redeclaration = false;<br>
> +          OldDecl = 0;<br>
> +        }<br>
> +      }<br>
> +    }<br>
> +  }<br>
><br>
>    // C++11 [dcl.constexpr]p8:<br>
>    //   A constexpr specifier for a non-static member function that is not<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Fri Jun 28 17:03:51 2013<br>
> @@ -977,21 +977,12 @@ Sema::CheckOverload(Scope *S, FunctionDe<br>
>    return Ovl_Overload;<br>
>  }<br>
><br>
> -static bool canBeOverloaded(const FunctionDecl &D) {<br>
> -  if (D.getAttr<OverloadableAttr>())<br>
> -    return true;<br>
> -  if (D.isExternC())<br>
> -    return false;<br>
> -<br>
> -  // Main cannot be overloaded (basic.start.main).<br>
> -  if (D.isMain())<br>
> +bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,<br>
> +                      bool UseUsingDeclRules) {<br>
> +  // C++ [basic.start.main]p2: This function shall not be overloaded.<br>
> +  if (New->isMain())<br>
>      return false;<br>
><br>
> -  return true;<br>
> -}<br>
> -<br>
> -static bool shouldTryToOverload(Sema &S, FunctionDecl *New, FunctionDecl *Old,<br>
> -                                bool UseUsingDeclRules) {<br>
>    FunctionTemplateDecl *OldTemplate = Old->getDescribedFunctionTemplate();<br>
>    FunctionTemplateDecl *NewTemplate = New->getDescribedFunctionTemplate();<br>
><br>
> @@ -1002,8 +993,8 @@ static bool shouldTryToOverload(Sema &S,<br>
>      return true;<br>
><br>
>    // Is the function New an overload of the function Old?<br>
> -  QualType OldQType = S.Context.getCanonicalType(Old->getType());<br>
> -  QualType NewQType = S.Context.getCanonicalType(New->getType());<br>
> +  QualType OldQType = Context.getCanonicalType(Old->getType());<br>
> +  QualType NewQType = Context.getCanonicalType(New->getType());<br>
><br>
>    // Compare the signatures (C++ 1.3.10) of the two functions to<br>
>    // determine whether they are overloads. If we find any mismatch<br>
> @@ -1024,7 +1015,7 @@ static bool shouldTryToOverload(Sema &S,<br>
>    if (OldQType != NewQType &&<br>
>        (OldType->getNumArgs() != NewType->getNumArgs() ||<br>
>         OldType->isVariadic() != NewType->isVariadic() ||<br>
> -       !S.FunctionArgTypesAreEqual(OldType, NewType)))<br>
> +       !FunctionArgTypesAreEqual(OldType, NewType)))<br>
>      return true;<br>
><br>
>    // C++ [temp.over.link]p4:<br>
> @@ -1040,9 +1031,9 @@ static bool shouldTryToOverload(Sema &S,<br>
>    // However, we don't consider either of these when deciding whether<br>
>    // a member introduced by a shadow declaration is hidden.<br>
>    if (!UseUsingDeclRules && NewTemplate &&<br>
> -      (!S.TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),<br>
> -                                         OldTemplate->getTemplateParameters(),<br>
> -                                         false, S.TPL_TemplateMatch) ||<br>
> +      (!TemplateParameterListsAreEqual(NewTemplate->getTemplateParameters(),<br>
> +                                       OldTemplate->getTemplateParameters(),<br>
> +                                       false, TPL_TemplateMatch) ||<br>
>         OldType->getResultType() != NewType->getResultType()))<br>
>      return true;<br>
><br>
> @@ -1068,9 +1059,9 @@ static bool shouldTryToOverload(Sema &S,<br>
>          //     declarations with the same name, the same parameter-type-list, and<br>
>          //     the same template parameter lists cannot be overloaded if any of<br>
>          //     them, but not all, have a ref-qualifier (8.3.5).<br>
> -        S.Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)<br>
> +        Diag(NewMethod->getLocation(), diag::err_ref_qualifier_overload)<br>
>            << NewMethod->getRefQualifier() << OldMethod->getRefQualifier();<br>
> -        S.Diag(OldMethod->getLocation(), diag::note_previous_declaration);<br>
> +        Diag(OldMethod->getLocation(), diag::note_previous_declaration);<br>
>        }<br>
>        return true;<br>
>      }<br>
> @@ -1080,7 +1071,7 @@ static bool shouldTryToOverload(Sema &S,<br>
>      // or non-static member function). Add it now, on the assumption that this<br>
>      // is a redeclaration of OldMethod.<br>
>      unsigned NewQuals = NewMethod->getTypeQualifiers();<br>
> -    if (!S.getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&<br>
> +    if (!getLangOpts().CPlusPlus1y && NewMethod->isConstexpr() &&<br>
>          !isa<CXXConstructorDecl>(NewMethod))<br>
>        NewQuals |= Qualifiers::Const;<br>
>      if (OldMethod->getTypeQualifiers() != NewQuals)<br>
> @@ -1091,19 +1082,6 @@ static bool shouldTryToOverload(Sema &S,<br>
>    return false;<br>
>  }<br>
><br>
> -bool Sema::IsOverload(FunctionDecl *New, FunctionDecl *Old,<br>
> -                      bool UseUsingDeclRules) {<br>
> -  if (!shouldTryToOverload(*this, New, Old, UseUsingDeclRules))<br>
> -    return false;<br>
> -<br>
> -  // If both of the functions are extern "C", then they are not<br>
> -  // overloads.<br>
> -  if (!canBeOverloaded(*Old) && !canBeOverloaded(*New))<br>
> -    return false;<br>
> -<br>
> -  return true;<br>
> -}<br>
> -<br>
>  /// \brief Checks availability of the function depending on the current<br>
>  /// function context. Inside an unavailable function, unavailability is ignored.<br>
>  ///<br>
><br>
> Modified: cfe/trunk/test/CXX/class.access/class.friend/p1.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p1.cpp?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/class.access/class.friend/p1.cpp?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CXX/class.access/class.friend/p1.cpp (original)<br>
> +++ cfe/trunk/test/CXX/class.access/class.friend/p1.cpp Fri Jun 28 17:03:51 2013<br>
> @@ -287,22 +287,22 @@ namespace test9 {<br>
><br>
>  // PR7230<br>
>  namespace test10 {<br>
> -  extern "C" void f(void);<br>
> -  extern "C" void g(void);<br>
> +  extern "C" void test10_f(void);<br>
> +  extern "C" void test10_g(void);<br>
><br>
>    namespace NS {<br>
>      class C {<br>
>        void foo(void); // expected-note {{declared private here}}<br>
> -      friend void test10::f(void);<br>
> +      friend void test10::test10_f(void);<br>
>      };<br>
>      static C* bar;<br>
>    }<br>
><br>
> -  void f(void) {<br>
> +  void test10_f(void) {<br>
>      NS::bar->foo();<br>
>    }<br>
><br>
> -  void g(void) {<br>
> +  void test10_g(void) {<br>
>      NS::bar->foo(); // expected-error {{private member}}<br>
>    }<br>
>  }<br>
><br>
> Modified: cfe/trunk/test/Sema/overloadable.c<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/overloadable.c?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/overloadable.c?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/Sema/overloadable.c (original)<br>
> +++ cfe/trunk/test/Sema/overloadable.c Fri Jun 28 17:03:51 2013<br>
> @@ -69,3 +69,18 @@ void test() {<br>
>    f0();<br>
>    f1();<br>
>  }<br>
> +<br>
> +void before_local_1(int) __attribute__((overloadable)); // expected-note {{here}}<br>
> +void before_local_2(int); // expected-note {{here}}<br>
> +void before_local_3(int) __attribute__((overloadable));<br>
> +void local() {<br>
> +  void before_local_1(char); // expected-error {{must have the 'overloadable' attribute}}<br>
> +  void before_local_2(char) __attribute__((overloadable)); // expected-error {{conflicting types}}<br>
> +  void before_local_3(char) __attribute__((overloadable));<br>
> +  void after_local_1(char); // expected-note {{here}}<br>
> +  void after_local_2(char) __attribute__((overloadable)); // expected-note {{here}}<br>
> +  void after_local_3(char) __attribute__((overloadable));<br>
> +}<br>
> +void after_local_1(int) __attribute__((overloadable)); // expected-error {{conflicting types}}<br>
> +void after_local_2(int); // expected-error {{must have the 'overloadable' attribute}}<br>
> +void after_local_3(int) __attribute__((overloadable));<br>
><br>
> Modified: cfe/trunk/test/SemaCXX/extern-c.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/extern-c.cpp?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/extern-c.cpp?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/SemaCXX/extern-c.cpp (original)<br>
> +++ cfe/trunk/test/SemaCXX/extern-c.cpp Fri Jun 28 17:03:51 2013<br>
> @@ -3,20 +3,20 @@<br>
>  namespace test1 {<br>
>    extern "C" {<br>
>      void test1_f() {<br>
> -      void test1_g(int); // expected-note {{previous declaration is here}}<br>
> +      void test1_g(int); // expected-note {{declared with C language linkage here}}<br>
>      }<br>
>    }<br>
>  }<br>
> -int test1_g(int); // expected-error {{functions that differ only in their return type cannot be overloaded}}<br>
> +int test1_g(int); // expected-error {{declaration of 'test1_g' in global scope conflicts with declaration with C language linkage}}<br>
><br>
>  namespace test2 {<br>
>    extern "C" {<br>
>      void test2_f() {<br>
> -      extern int test2_x; // expected-note {{previous definition is here}}<br>
> +      extern int test2_x; // expected-note {{declared with C language linkage here}}<br>
>      }<br>
>    }<br>
>  }<br>
> -float test2_x; // expected-error {{redefinition of 'test2_x' with a different type: 'float' vs 'int'}}<br>
> +float test2_x; // expected-error {{declaration of 'test2_x' in global scope conflicts with declaration with C language linkage}}<br>
><br>
>  namespace test3 {<br>
>    extern "C" {<br>
> @@ -31,18 +31,18 @@ namespace test3 {<br>
><br>
>  extern "C" {<br>
>    void test4_f() {<br>
> -    extern int test4_b; // expected-note {{previous definition is here}}<br>
> +    extern int test4_b; // expected-note {{declared with C language linkage here}}<br>
>    }<br>
>  }<br>
> -static float test4_b; // expected-error {{redefinition of 'test4_b' with a different type: 'float' vs 'int'}}<br>
> +static float test4_b; // expected-error {{declaration of 'test4_b' in global scope conflicts with declaration with C language linkage}}<br>
><br>
>  extern "C" {<br>
>    void test5_f() {<br>
> -    extern int test5_b; // expected-note {{previous definition is here}}<br>
> +    extern int test5_b; // expected-note {{declared with C language linkage here}}<br>
>    }<br>
>  }<br>
>  extern "C" {<br>
> -  static float test5_b; // expected-error {{redefinition of 'test5_b' with a different type: 'float' vs 'int'}}<br>
> +  static float test5_b; // expected-error {{declaration of 'test5_b' in global scope conflicts with declaration with C language linkage}}<br>
>  }<br>
><br>
>  extern "C" {<br>
> @@ -69,11 +69,11 @@ namespace linkage {<br>
>      }<br>
>    }<br>
>    namespace from_outer {<br>
> -    void linkage_from_outer_1();<br>
> +    void linkage_from_outer_1(); // expected-note {{previous}}<br>
>      void linkage_from_outer_2(); // expected-note {{previous}}<br>
>      extern "C" {<br>
> -      void linkage_from_outer_1(int); // expected-note {{previous}}<br>
> -      void linkage_from_outer_1(); // expected-error {{conflicting types}}<br>
> +      void linkage_from_outer_1(int);<br>
> +      void linkage_from_outer_1(); // expected-error {{different language linkage}}<br>
>        void linkage_from_outer_2(); // expected-error {{different language linkage}}<br>
>      }<br>
>    }<br>
> @@ -98,11 +98,44 @@ namespace linkage {<br>
>    }<br>
>  }<br>
><br>
> -void lookup_in_global_f();<br>
> +void lookup_in_global_f(); // expected-note {{here}}<br>
>  namespace lookup_in_global {<br>
>    void lookup_in_global_f();<br>
> +  void lookup_in_global_g();<br>
>    extern "C" {<br>
> -    // FIXME: We should reject this.<br>
> -    void lookup_in_global_f(int);<br>
> +    void lookup_in_global_f(int); // expected-error {{conflicts with declaration in global scope}}<br>
> +    void lookup_in_global_g(int); // expected-note {{here}}<br>
>    }<br>
>  }<br>
> +void lookup_in_global_g(); // expected-error {{conflicts with declaration with C language linkage}}<br>
> +<br>
> +namespace N1 {<br>
> +  extern "C" int different_kind_1; // expected-note {{here}}<br>
> +  extern "C" void different_kind_2(); // expected-note {{here}}<br>
> +}<br>
> +namespace N2 {<br>
> +  extern "C" void different_kind_1(); // expected-error {{different kind of symbol}}<br>
> +  extern "C" int different_kind_2; // expected-error {{different kind of symbol}}<br>
> +}<br>
> +<br>
> +extern "C" {<br>
> +  struct stat {};<br>
> +  void stat(struct stat);<br>
> +}<br>
> +namespace X {<br>
> +  extern "C" {<br>
> +    void stat(struct ::stat);<br>
> +  }<br>
> +}<br>
> +<br>
> +extern "C" void name_with_using_decl_1(int);<br>
> +namespace using_decl {<br>
> +  void name_with_using_decl_1();<br>
> +  void name_with_using_decl_2();<br>
> +  void name_with_using_decl_3();<br>
> +}<br>
> +using using_decl::name_with_using_decl_1;<br>
> +using using_decl::name_with_using_decl_2;<br>
> +extern "C" void name_with_using_decl_2(int);<br>
> +extern "C" void name_with_using_decl_3(int);<br>
> +using using_decl::name_with_using_decl_3;<br>
><br>
> Modified: cfe/trunk/test/SemaCXX/friend.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/friend.cpp?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/friend.cpp?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/SemaCXX/friend.cpp (original)<br>
> +++ cfe/trunk/test/SemaCXX/friend.cpp Fri Jun 28 17:03:51 2013<br>
> @@ -134,7 +134,7 @@ namespace test6_3 {<br>
>  namespace test7 {<br>
>    extern "C" {<br>
>      class X {<br>
> -      friend int f() { return 42; }<br>
> +      friend int test7_f() { return 42; }<br>
>      };<br>
>    }<br>
>  }<br>
><br>
> Modified: cfe/trunk/test/SemaCXX/linkage-spec.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage-spec.cpp?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage-spec.cpp?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/SemaCXX/linkage-spec.cpp (original)<br>
> +++ cfe/trunk/test/SemaCXX/linkage-spec.cpp Fri Jun 28 17:03:51 2013<br>
> @@ -41,20 +41,32 @@ namespace pr5430 {<br>
>  using namespace pr5430;<br>
>  extern "C" void pr5430::func(void) { }<br>
><br>
> -// PR5404<br>
> -int f2(char *)<br>
> +// PR5405<br>
> +int f2(char *) // expected-note {{here}}<br>
>  {<br>
>          return 0;<br>
>  }<br>
><br>
>  extern "C"<br>
>  {<br>
> -    int f2(int)<br>
> +    int f2(int) // expected-error {{with C language linkage conflicts with declaration in global scope}}<br>
>      {<br>
>          return f2((char *)0);<br>
>      }<br>
>  }<br>
><br>
> +namespace PR5405 {<br>
> +  int f2b(char *) {<br>
> +    return 0;<br>
> +  }<br>
> +<br>
> +  extern "C" {<br>
> +    int f2b(int) {<br>
> +      return f2b((char *)0); // ok<br>
> +    }<br>
> +  }<br>
> +}<br>
> +<br>
>  // PR6991<br>
>  extern "C" typedef int (*PutcFunc_t)(int);<br>
><br>
> @@ -117,3 +129,28 @@ namespace pr14958 {<br>
><br>
>  extern "C" void PR16167; // expected-error {{variable has incomplete type 'void'}}<br>
>  extern void PR16167_0; // expected-error {{variable has incomplete type 'void'}}<br>
> +<br>
> +// PR7927<br>
> +enum T_7927 {<br>
> +  E_7927<br>
> +};<br>
> +<br>
> +extern "C" void f_pr7927(int);<br>
> +<br>
> +namespace {<br>
> +  extern "C" void f_pr7927(int);<br>
> +<br>
> +  void foo_pr7927() {<br>
> +    f_pr7927(E_7927);<br>
> +    f_pr7927(0);<br>
> +    ::f_pr7927(E_7927);<br>
> +    ::f_pr7927(0);<br>
> +  }<br>
> +}<br>
> +<br>
> +void bar_pr7927() {<br>
> +  f_pr7927(E_7927);<br>
> +  f_pr7927(0);<br>
> +  ::f_pr7927(E_7927);<br>
> +  ::f_pr7927(0);<br>
> +}<br>
><br>
> Modified: cfe/trunk/test/SemaCXX/linkage2.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage2.cpp?rev=185229&r1=185228&r2=185229&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/linkage2.cpp?rev=185229&r1=185228&r2=185229&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/SemaCXX/linkage2.cpp (original)<br>
> +++ cfe/trunk/test/SemaCXX/linkage2.cpp Fri Jun 28 17:03:51 2013<br>
> @@ -201,3 +201,15 @@ namespace test18 {<br>
>    }<br>
>    void *h() { return f(); }<br>
>  }<br>
> +<br>
> +extern "C" void pr16247_foo(int); // expected-note {{here}}<br>
> +static void pr16247_foo(double); // expected-error {{conflicts with declaration with C language linkage}}<br>
> +void pr16247_foo(int) {}<br>
> +void pr16247_foo(double) {}<br>
> +<br>
> +namespace PR16247 {<br>
> +  extern "C" void pr16247_bar(int);<br>
> +  static void pr16247_bar(double);<br>
> +  void pr16247_bar(int) {}<br>
> +  void pr16247_bar(double) {}<br>
> +}<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</div></div></blockquote></div><br></div>