r313729 - Implement C++ [basic.link]p8.

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 20 00:22:00 PDT 2017


Author: rsmith
Date: Wed Sep 20 00:22:00 2017
New Revision: 313729

URL: http://llvm.org/viewvc/llvm-project?rev=313729&view=rev
Log:
Implement C++ [basic.link]p8.

If a function or variable has a type with no linkage (and is not extern "C"),
any use of it requires a definition within the same translation unit; the idea
is that it is not possible to define the entity elsewhere, so any such use is
necessarily an error.

There is an exception, though: some types formally have no linkage but
nonetheless can be referenced from other translation units (for example, this
happens to anonymous structures defined within inline functions). For entities
with those types, we suppress the diagnostic except under -pedantic.

Added:
    cfe/trunk/test/CXX/basic/basic.link/p8.cpp
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/include/clang/Sema/SemaInternal.h
    cfe/trunk/lib/AST/Decl.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaExpr.cpp
    cfe/trunk/test/Analysis/malloc.mm
    cfe/trunk/test/Analysis/reference.cpp
    cfe/trunk/test/CodeGenCXX/debug-info-method.cpp
    cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp
    cfe/trunk/test/CodeGenCXX/mangle.cpp
    cfe/trunk/test/PCH/cxx11-lambdas.mm
    cfe/trunk/test/SemaCXX/warn-unreachable.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Sep 20 00:22:00 2017
@@ -4707,6 +4707,14 @@ def note_deleted_assign_field : Note<
 def warn_undefined_internal : Warning<
   "%select{function|variable}0 %q1 has internal linkage but is not defined">,
   InGroup<DiagGroup<"undefined-internal">>;
+def err_undefined_internal_type : Error<
+  "%select{function|variable}0 %q1 is used but not defined in this "
+  "translation unit, and cannot be defined in any other translation unit "
+  "because its type does not have linkage">;
+def ext_undefined_internal_type : Extension<
+  "ISO C++ requires a definition in this translation unit for "
+  "%select{function|variable}0 %q1 because its type does not have linkage">,
+  InGroup<DiagGroup<"undefined-internal-type">>;
 def warn_undefined_inline : Warning<"inline function %q0 is not defined">,
   InGroup<DiagGroup<"undefined-inline">>;
 def err_undefined_inline_var : Error<"inline variable %q0 is not defined">;

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Wed Sep 20 00:22:00 2017
@@ -1086,6 +1086,11 @@ public:
   /// definition in this translation unit.
   llvm::MapVector<NamedDecl *, SourceLocation> UndefinedButUsed;
 
+  /// Determine if VD, which must be a variable or function, is an external
+  /// symbol that nonetheless can't be referenced from outside this translation
+  /// unit because its type has no linkage and it's not extern "C".
+  bool isExternalWithNoLinkageType(ValueDecl *VD);
+
   /// Obtain a sorted list of functions that are undefined but ODR-used.
   void getUndefinedButUsed(
       SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> > &Undefined);

Modified: cfe/trunk/include/clang/Sema/SemaInternal.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaInternal.h?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/SemaInternal.h (original)
+++ cfe/trunk/include/clang/Sema/SemaInternal.h Wed Sep 20 00:22:00 2017
@@ -73,7 +73,8 @@ inline void MarkVarDeclODRUsed(VarDecl *
   // Keep track of used but undefined variables.
   // FIXME: We shouldn't suppress this warning for static data members.
   if (Var->hasDefinition(SemaRef.Context) == VarDecl::DeclarationOnly &&
-      (!Var->isExternallyVisible() || Var->isInline()) &&
+      (!Var->isExternallyVisible() || Var->isInline() ||
+       SemaRef.isExternalWithNoLinkageType(Var)) &&
       !(Var->isStaticDataMember() && Var->hasInit())) {
     SourceLocation &old = SemaRef.UndefinedButUsed[Var->getCanonicalDecl()];
     if (old.isInvalid())

Modified: cfe/trunk/lib/AST/Decl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Decl.cpp (original)
+++ cfe/trunk/lib/AST/Decl.cpp Wed Sep 20 00:22:00 2017
@@ -721,8 +721,7 @@ LinkageComputer::getLVForNamespaceScopeD
     // because of this, but unique-external linkage suits us.
     if (Context.getLangOpts().CPlusPlus && !isFirstInExternCContext(Var)) {
       LinkageInfo TypeLV = getLVForType(*Var->getType(), computation);
-      if (TypeLV.getLinkage() != ExternalLinkage &&
-          TypeLV.getLinkage() != ModuleLinkage)
+      if (!isExternallyVisible(TypeLV.getLinkage()))
         return LinkageInfo::uniqueExternal();
       if (!LV.isVisibilityExplicit())
         LV.mergeVisibility(TypeLV);
@@ -772,7 +771,7 @@ LinkageComputer::getLVForNamespaceScopeD
       QualType TypeAsWritten = Function->getType();
       if (TypeSourceInfo *TSI = Function->getTypeSourceInfo())
         TypeAsWritten = TSI->getType();
-      if (TypeAsWritten->getLinkage() == UniqueExternalLinkage)
+      if (!isExternallyVisible(TypeAsWritten->getLinkage()))
         return LinkageInfo::uniqueExternal();
     }
 
@@ -909,7 +908,7 @@ LinkageComputer::getLVForClassMember(con
   const NamedDecl *explicitSpecSuppressor = nullptr;
 
   if (const auto *MD = dyn_cast<CXXMethodDecl>(D)) {
-    // If the type of the function uses a type with unique-external
+    // If the type of the function uses a type that has non-externally-visible
     // linkage, it's not legally usable from outside this translation unit.
     // But only look at the type-as-written. If this function has an
     // auto-deduced return type, we can't compute the linkage of that type
@@ -922,7 +921,7 @@ LinkageComputer::getLVForClassMember(con
       QualType TypeAsWritten = MD->getType();
       if (TypeSourceInfo *TSI = MD->getTypeSourceInfo())
         TypeAsWritten = TSI->getType();
-      if (TypeAsWritten->getLinkage() == UniqueExternalLinkage)
+      if (!isExternallyVisible(TypeAsWritten->getLinkage()))
         return LinkageInfo::uniqueExternal();
     }
     // If this is a method template specialization, use the linkage for
@@ -1119,6 +1118,9 @@ LinkageInfo LinkageComputer::getLVForClo
                                              Decl *ContextDecl,
                                              LVComputationKind computation) {
   // This lambda has its linkage/visibility determined by its owner.
+  // FIXME: This is wrong. A lambda never formally has linkage; if this
+  // calculation determines the lambda has external linkage, it should be
+  // downgraded to VisibleNoLinkage.
   if (ContextDecl) {
     if (isa<ParmVarDecl>(ContextDecl))
       DC = ContextDecl->getDeclContext()->getRedeclContext();

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Wed Sep 20 00:22:00 2017
@@ -582,6 +582,23 @@ static bool ShouldRemoveFromUnused(Sema
   return false;
 }
 
+static bool isFunctionOrVarDeclExternC(NamedDecl *ND) {
+  if (auto *FD = dyn_cast<FunctionDecl>(ND))
+    return FD->isExternC();
+  return cast<VarDecl>(ND)->isExternC();
+}
+
+/// Determine whether ND is an external-linkage function or variable whose
+/// type has no linkage.
+bool Sema::isExternalWithNoLinkageType(ValueDecl *VD) {
+  // Note: it's not quite enough to check whether VD has UniqueExternalLinkage,
+  // because we also want to catch the case where its type has VisibleNoLinkage,
+  // which does not affect the linkage of VD.
+  return getLangOpts().CPlusPlus && VD->hasExternalFormalLinkage() &&
+         !isExternalFormalLinkage(VD->getType()->getLinkage()) &&
+         !isFunctionOrVarDeclExternC(VD);
+}
+
 /// Obtains a sorted list of functions and variables that are undefined but
 /// ODR-used.
 void Sema::getUndefinedButUsed(
@@ -598,17 +615,27 @@ void Sema::getUndefinedButUsed(
     if (isa<CXXDeductionGuideDecl>(ND))
       continue;
 
+    if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
+      // An exported function will always be emitted when defined, so even if
+      // the function is inline, it doesn't have to be emitted in this TU. An
+      // imported function implies that it has been exported somewhere else.
+      continue;
+    }
+
     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) {
       if (FD->isDefined())
         continue;
       if (FD->isExternallyVisible() &&
+          !isExternalWithNoLinkageType(FD) &&
           !FD->getMostRecentDecl()->isInlined())
         continue;
     } else {
       auto *VD = cast<VarDecl>(ND);
       if (VD->hasDefinition() != VarDecl::DeclarationOnly)
         continue;
-      if (VD->isExternallyVisible() && !VD->getMostRecentDecl()->isInline())
+      if (VD->isExternallyVisible() &&
+          !isExternalWithNoLinkageType(VD) &&
+          !VD->getMostRecentDecl()->isInline())
         continue;
     }
 
@@ -626,33 +653,43 @@ static void checkUndefinedButUsed(Sema &
   S.getUndefinedButUsed(Undefined);
   if (Undefined.empty()) return;
 
-  for (SmallVectorImpl<std::pair<NamedDecl *, SourceLocation> >::iterator
-         I = Undefined.begin(), E = Undefined.end(); I != E; ++I) {
-    NamedDecl *ND = I->first;
-
-    if (ND->hasAttr<DLLImportAttr>() || ND->hasAttr<DLLExportAttr>()) {
-      // An exported function will always be emitted when defined, so even if
-      // the function is inline, it doesn't have to be emitted in this TU. An
-      // imported function implies that it has been exported somewhere else.
-      continue;
-    }
-
-    if (!ND->isExternallyVisible()) {
-      S.Diag(ND->getLocation(), diag::warn_undefined_internal)
-        << isa<VarDecl>(ND) << ND;
-    } else if (auto *FD = dyn_cast<FunctionDecl>(ND)) {
+  for (auto Undef : Undefined) {
+    ValueDecl *VD = cast<ValueDecl>(Undef.first);
+    SourceLocation UseLoc = Undef.second;
+
+    if (S.isExternalWithNoLinkageType(VD)) {
+      // C++ [basic.link]p8:
+      //   A type without linkage shall not be used as the type of a variable
+      //   or function with external linkage unless
+      //    -- the entity has C language linkage
+      //    -- the entity is not odr-used or is defined in the same TU
+      //
+      // As an extension, accept this in cases where the type is externally
+      // visible, since the function or variable actually can be defined in
+      // another translation unit in that case.
+      S.Diag(VD->getLocation(), isExternallyVisible(VD->getType()->getLinkage())
+                                    ? diag::ext_undefined_internal_type
+                                    : diag::err_undefined_internal_type)
+        << isa<VarDecl>(VD) << VD;
+    } else if (!VD->isExternallyVisible()) {
+      // FIXME: We can promote this to an error. The function or variable can't
+      // be defined anywhere else, so the program must necessarily violate the
+      // one definition rule.
+      S.Diag(VD->getLocation(), diag::warn_undefined_internal)
+        << isa<VarDecl>(VD) << VD;
+    } else if (auto *FD = dyn_cast<FunctionDecl>(VD)) {
       (void)FD;
       assert(FD->getMostRecentDecl()->isInlined() &&
              "used object requires definition but isn't inline or internal?");
       // FIXME: This is ill-formed; we should reject.
-      S.Diag(ND->getLocation(), diag::warn_undefined_inline) << ND;
+      S.Diag(VD->getLocation(), diag::warn_undefined_inline) << VD;
     } else {
-      assert(cast<VarDecl>(ND)->getMostRecentDecl()->isInline() &&
+      assert(cast<VarDecl>(VD)->getMostRecentDecl()->isInline() &&
              "used var requires definition but isn't inline or internal?");
-      S.Diag(ND->getLocation(), diag::err_undefined_inline_var) << ND;
+      S.Diag(VD->getLocation(), diag::err_undefined_inline_var) << VD;
     }
-    if (I->second.isValid())
-      S.Diag(I->second, diag::note_used_here);
+    if (UseLoc.isValid())
+      S.Diag(UseLoc, diag::note_used_here);
   }
 
   S.UndefinedButUsed.clear();

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Sep 20 00:22:00 2017
@@ -3827,7 +3827,7 @@ void Sema::MergeVarDecl(VarDecl *New, Lo
     }
   }
 
-  // If this redeclaration makes the function inline, we may need to add it to
+  // If this redeclaration makes the variable inline, we may need to add it to
   // UndefinedButUsed.
   if (!Old->isInline() && New->isInline() && Old->isUsed(false) &&
       !Old->getDefinition() && !New->isThisDeclarationADefinition())
@@ -12329,18 +12329,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl
       }
     }
 
-    // The only way to be included in UndefinedButUsed is if there is an
-    // ODR use before the definition. Avoid the expensive map lookup if this
-    // is the first declaration.
-    if (!FD->isFirstDecl() && FD->getPreviousDecl()->isUsed()) {
-      if (!FD->isExternallyVisible())
-        UndefinedButUsed.erase(FD);
-      else if (FD->isInlined() &&
-               !LangOpts.GNUInline &&
-               (!FD->getPreviousDecl()->hasAttr<GNUInlineAttr>()))
-        UndefinedButUsed.erase(FD);
-    }
-
     // If the function implicitly returns zero (like 'main') or is naked,
     // don't complain about missing return statements.
     if (FD->hasImplicitReturnZero() || FD->hasAttr<NakedAttr>())

Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Sep 20 00:22:00 2017
@@ -13897,6 +13897,8 @@ void Sema::MarkFunctionReferenced(Source
              !LangOpts.GNUInline &&
              !Func->getMostRecentDecl()->hasAttr<GNUInlineAttr>())
       UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
+    else if (isExternalWithNoLinkageType(Func))
+      UndefinedButUsed.insert(std::make_pair(Func->getCanonicalDecl(), Loc));
   }
 
   Func->markUsed(Context);

Modified: cfe/trunk/test/Analysis/malloc.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.mm?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.mm (original)
+++ cfe/trunk/test/Analysis/malloc.mm Wed Sep 20 00:22:00 2017
@@ -187,7 +187,7 @@ typedef volatile struct {
  void *opaque1;
  long opaque2;
 } OSQueueHead;
-void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __attribute__((weak_import));
+extern "C" void OSAtomicEnqueue( OSQueueHead *__list, void *__new, size_t __offset) __attribute__((weak_import));
 static inline void radar11111210(OSQueueHead *pool) {
     void *newItem = malloc(4);
     OSAtomicEnqueue(pool, newItem, 4);

Modified: cfe/trunk/test/Analysis/reference.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/reference.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/reference.cpp (original)
+++ cfe/trunk/test/Analysis/reference.cpp Wed Sep 20 00:22:00 2017
@@ -117,6 +117,11 @@ void testRetroactiveNullReference(int *x
   y = 5; // expected-warning{{Dereference of null pointer}}
 }
 
+namespace TestReferenceAddress {
+struct S { int &x; };
+S getS();
+S *getSP();
+
 void testReferenceAddress(int &x) {
 // FIXME: Move non-zero reference assumption out of RangeConstraintManager.cpp:422
 #ifdef ANALYZER_CM_Z3
@@ -127,23 +132,19 @@ void testReferenceAddress(int &x) {
   clang_analyzer_eval(&ref() != 0); // expected-warning{{TRUE}}
 #endif
 
-  struct S { int &x; };
-
-  extern S getS();
 #ifdef ANALYZER_CM_Z3
   clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}}
 #else
   clang_analyzer_eval(&getS().x != 0); // expected-warning{{TRUE}}
 #endif
 
-  extern S *getSP();
 #ifdef ANALYZER_CM_Z3
   clang_analyzer_eval(&getSP()->x != 0); // expected-warning{{UNKNOWN}}
 #else
   clang_analyzer_eval(&getSP()->x != 0); // expected-warning{{TRUE}}
 #endif
 }
-
+}
 
 void testFunctionPointerReturn(void *opaque) {
   typedef int &(*RefFn)();

Added: cfe/trunk/test/CXX/basic/basic.link/p8.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.link/p8.cpp?rev=313729&view=auto
==============================================================================
--- cfe/trunk/test/CXX/basic/basic.link/p8.cpp (added)
+++ cfe/trunk/test/CXX/basic/basic.link/p8.cpp Wed Sep 20 00:22:00 2017
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s -pedantic
+
+template<typename T> struct Template {};
+
+struct Linkage1 { struct Inner {}; };
+typedef struct { struct Inner {}; } Linkage2;
+
+typedef struct {} const NoLinkage1;
+auto x = [] {};
+typedef decltype(x) NoLinkage2;
+auto f() { return [] {}; }
+typedef decltype(f()) NoLinkage3;
+
+inline auto g() { return [] {}; }
+typedef decltype(g()) VisibleNoLinkage1;
+inline auto y = [] {};
+typedef decltype(x) VisibleNoLinkage2;
+inline auto h() { struct {} x; return x; }
+typedef decltype(h()) VisibleNoLinkage3;
+
+extern Linkage1 linkage1v;
+extern Linkage1::Inner linkage1iv;
+extern Linkage2 linkage2v;
+extern Linkage2::Inner linkage2iv;
+extern Template<Linkage1> linkaget1v;
+extern Linkage1 linkage1f();
+void linkage2f(Linkage2);
+
+void use_linkage() {
+  &linkage1v, &linkage1iv, &linkage2v, &linkage2iv, &linkaget1v; // expected-warning 5{{unused}}
+  linkage1f();
+  linkage2f({});
+}
+
+extern NoLinkage1 no_linkage1(); // expected-error {{function 'no_linkage1' is used but not defined in this translation unit}}
+extern NoLinkage2 no_linkage2(); // expected-error {{function 'no_linkage2' is used but not defined in this translation unit}}
+extern NoLinkage3 no_linkage3(); // expected-error {{function 'no_linkage3' is used but not defined in this translation unit}}
+
+void use_no_linkage() {
+  no_linkage1(); // expected-note {{used here}}
+  no_linkage2(); // expected-note {{used here}}
+  no_linkage3(); // expected-note {{used here}}
+}
+
+// FIXME: This should emit an extension warning. It does not because we
+// incorrectly give the lambda external linkage.
+extern VisibleNoLinkage1 visible_no_linkage1();
+
+// FIXME: We should accept this as an extension. We don't because we
+// incorrectly give the lambda no linkage instead of "VisibleNoLinkage".
+extern VisibleNoLinkage2 visible_no_linkage2(); // expected-error {{used but not defined}}
+
+// This case is correctly accepted as an extension.
+extern VisibleNoLinkage3 visible_no_linkage3(); // expected-warning {{ISO C++ requires a definition}}
+
+void use_visible_no_linkage() {
+  visible_no_linkage1();
+  visible_no_linkage2(); // expected-note {{used here}}
+  visible_no_linkage3(); // expected-note {{used here}}
+}
+
+
+extern inline int not_defined; // expected-error {{not defined}}
+extern inline int defined_after_use;
+void use_inline_vars() {
+  not_defined = 1; // expected-note {{used here}}
+  defined_after_use = 2;
+}
+inline int defined_after_use;

Modified: cfe/trunk/test/CodeGenCXX/debug-info-method.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-method.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/debug-info-method.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/debug-info-method.cpp Wed Sep 20 00:22:00 2017
@@ -20,6 +20,7 @@ union {
 class A {
 protected:
   void foo(int, A, decltype(u));
+  void bar();
 }; 
 
 void A::foo(int, A, decltype(u)) {
@@ -29,3 +30,5 @@ A a;
 
 int A::*x = 0;
 int (A::*y)(int) = 0;
+
+void A::bar() { foo(0, *this, u); }

Modified: cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-ms-cxx11.cpp Wed Sep 20 00:22:00 2017
@@ -160,6 +160,8 @@ struct { } a;
 decltype(a) fun(decltype(a) x, decltype(a)) { return x; }
 // CHECK-DAG: @"\01?fun at PR18022@@YA?AU<unnamed-type-a>@1 at U21@0 at Z"
 
+void use_fun() { fun(a, a); }
+
 }
 
 inline int define_lambda() {
@@ -280,7 +282,7 @@ void g() {
 
 namespace PR18204 {
 template <typename T>
-int f(T *);
+int f(T *) { return 0; }
 static union {
   int n = f(this);
 };
@@ -346,4 +348,5 @@ int call_it = (A::default_args(), 1);
 
 enum { enumerator };
 void f(decltype(enumerator)) {}
-// CHECK-DAG: define void @"\01?f@@YAXW4<unnamed-enum-enumerator>@@@Z"(
+// CHECK-DAG: define internal void @"\01?f@@YAXW4<unnamed-enum-enumerator>@@@Z"(
+void use_f() { f(enumerator); }

Modified: cfe/trunk/test/CodeGenCXX/mangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle.cpp Wed Sep 20 00:22:00 2017
@@ -893,7 +893,8 @@ namespace test39 {
     struct {} a;
   } *foo;
   template<typename T> void func(T) {}
-  void test(foo x) {
+  void test() {
+    foo x;
     func(x->a);
   }
 }

Modified: cfe/trunk/test/PCH/cxx11-lambdas.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx11-lambdas.mm?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/test/PCH/cxx11-lambdas.mm (original)
+++ cfe/trunk/test/PCH/cxx11-lambdas.mm Wed Sep 20 00:22:00 2017
@@ -39,7 +39,7 @@ int init_capture(T t) {
 }
 
 struct X {
-  template <typename T> X(T);
+  template <typename T> X(T) {}
 };
 struct Y { Y(const X &x = [] {}); };
 

Modified: cfe/trunk/test/SemaCXX/warn-unreachable.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-unreachable.cpp?rev=313729&r1=313728&r2=313729&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/warn-unreachable.cpp (original)
+++ cfe/trunk/test/SemaCXX/warn-unreachable.cpp Wed Sep 20 00:22:00 2017
@@ -49,22 +49,26 @@ void test3() {
       (halt()); // expected-warning {{will never be executed}}
 }
 
-void test4() {
+namespace Test4 {
   struct S {
     int mem;
   } s;
   S &foor();
-  halt(), foor()// expected-warning {{will never be executed}}
-    .mem;       
+  void test4() {
+    halt(), foor()// expected-warning {{will never be executed}}
+      .mem;       
+  }
 }
 
-void test5() {
+namespace Test5 {
   struct S {
     int mem;
   } s;
   S &foonr() __attribute__((noreturn));
-  foonr()
-    .mem;       // expected-warning {{will never be executed}}
+  void test5() {
+    foonr()
+      .mem;       // expected-warning {{will never be executed}}
+  }
 }
 
 void test6() {




More information about the cfe-commits mailing list