Re: [PATCH] D33705: [CGVTables] Finalize SP before attempting to clone it

2017-05-30 Thread Keno Fischer via cfe-commits
For some reason your comments aren't showing up on Phabricator, so replying
via email - hope everybody sees it.

If SPs are now all finalized early - I'm assuming there's some other code
> that finalizes SPs that's no longer needed?
>

Not all of them, just the one before cloning. I wanted to make the minimal
change possible here, since this already seems like a bit of a hack to work
around the fact that we can't properly forward variadic function calls at
the IR level.


> Also - this seems like a layering/separation issue - does other code call
> into the DI as casually/explicitly as this code being added to CGVTables?
> (Or should the callback go through some more generic entry point in
> CGDebugInfo to delegate/handle that?) & is there nothing in CGDebugInfo
> that is already called back in a timely fashion to handle this? I'm
> guessing what's needed is a "IR has finished being generated for this
> function, opt/codegen is about to start"? That seems like a good generic
> callback & probably shouldn't be coming from something called CGVTables?
> (presuming there's a more general place to put that)
>

I suppose there's CGDebugInfo::EmitFunctionEnd, so if we did want to
finalize every SP as soon as we're done with it, we could put an explicit
call to that extent there. Frankly though I don't really know the clang
code too well, I just want to unbreak LLVM ;).
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24371: Add diagnostics to require_constant_initialization

2017-05-31 Thread Keno Fischer via cfe-commits
Go for it

On May 31, 2017 20:07, "Eric Fiselier via Phabricator" <
revi...@reviews.llvm.org> wrote:

> EricWF added a comment.
>
> @loladiro The patch doesn't apply correctly to the test. Do you mind if I
> hijack this and fix it?
>
>
> Repository:
>   rL LLVM
>
> https://reviews.llvm.org/D24371
>
>
>
>
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r304451 - [SemaCXX] Add diagnostics to require_constant_initialization

2017-06-01 Thread Keno Fischer via cfe-commits
Author: kfischer
Date: Thu Jun  1 13:54:16 2017
New Revision: 304451

URL: http://llvm.org/viewvc/llvm-project?rev=304451&view=rev
Log:
[SemaCXX] Add diagnostics to require_constant_initialization

Summary:
This hooks up the detailed diagnostics of why constant initialization was
not possible if require_constant_initialization reports an error.
I have updated the test to account for the new notes.

Reviewed By: EricWF
Subscribers: cfe-commits
Differential Revision: https://reviews.llvm.org/D24371

Modified:
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=304451&r1=304450&r2=304451&view=diff
==
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Jun  1 13:54:16 2017
@@ -6,6 +6,17 @@ void Sema::CheckCompleteVariableDeclarat
   << Init->getSourceRange();
 Diag(attr->getLocation(), 
diag::note_declared_required_constant_init_here)
   << attr->getRange();
+if (getLangOpts().CPlusPlus11) {
+  APValue Value;
+  SmallVector Notes;
+  Init->EvaluateAsInitializer(Value, getASTContext(), var, Notes);
+  for (auto &it : Notes)
+Diag(it.first, it.second);
+} else {
+  Diag(CacheCulprit->getExprLoc(),
+   diag::note_invalid_subexpr_in_const_expr)
+  << CacheCulprit->getSourceRange();
+}
   }
 }
 else if (!var->isConstexpr() && IsGlobal &&

Modified: cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp?rev=304451&r1=304450&r2=304451&view=diff
==
--- cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp (original)
+++ cfe/trunk/test/SemaCXX/attr-require-constant-initialization.cpp Thu Jun  1 
13:54:16 2017
@@ -7,9 +7,9 @@
 
 #define ATTR __attribute__((require_constant_initialization)) // expected-note 
0+ {{expanded from macro}}
 
-int ReturnInt();
+int ReturnInt(); // expected-note 0+ {{declared here}}
 
-struct PODType {
+struct PODType { // expected-note 0+ {{declared here}}
   int value;
   int value2;
 };
@@ -20,20 +20,20 @@ struct PODType {
 struct LitType {
   constexpr LitType() : value(0) {}
   constexpr LitType(int x) : value(x) {}
-  LitType(void *) : value(-1) {}
+  LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}}
   int value;
 };
 #endif
 
-struct NonLit {
+struct NonLit { // expected-note 0+ {{declared here}}
 #if __cplusplus >= 201402L
   constexpr NonLit() : value(0) {}
   constexpr NonLit(int x) : value(x) {}
 #else
-  NonLit() : value(0) {}
+  NonLit() : value(0) {} // expected-note 0+ {{declared here}}
   NonLit(int x) : value(x) {}
 #endif
-  NonLit(void *) : value(-1) {}
+  NonLit(void *) : value(-1) {} // expected-note 0+ {{declared here}}
   ~NonLit() {}
   int value;
 };
@@ -43,7 +43,7 @@ struct StoresNonLit {
   constexpr StoresNonLit() : obj() {}
   constexpr StoresNonLit(int x) : obj(x) {}
 #else
-  StoresNonLit() : obj() {}
+  StoresNonLit() : obj() {} // expected-note 0+ {{declared here}}
   StoresNonLit(int x) : obj(x) {}
 #endif
   StoresNonLit(void *p) : obj(p) {}
@@ -82,6 +82,12 @@ void test_basic_start_static_2_1() {
   const int non_global = 42;
   ATTR static const int &local_init = non_global; // expected-error {{variable 
does not have a constant initializer}}
   // expected-note@-1 {{required by 'require_constant_initialization' 
attribute here}}
+#if __cplusplus >= 201103L
+  // expected-note@-3 {{reference to 'non_global' is not a constant 
expression}}
+  // expected-note@-5 {{declared here}}
+#else
+  // expected-note@-6 {{subexpression not valid in a constant expression}}
+#endif
   ATTR static const int &global_init = glvalue_int;
   ATTR static const int &temp_init = 42;
 }
@@ -89,8 +95,18 @@ void test_basic_start_static_2_1() {
 ATTR const int &temp_ref = 42;
 ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not 
have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initialization' attribute 
here}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a 
constant expression}}
+#else
+// expected-note@-5 {{subexpression not valid in a constant expression}}
+#endif
 ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not 
have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initialization' attribute 
here}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a 
constant expression}}
+#else
+// expected-note@-5 {{subexpression not val

r304470 - [CGDebugInfo] Finalize SubPrograms when we're done with them

2017-06-01 Thread Keno Fischer via cfe-commits
Author: kfischer
Date: Thu Jun  1 16:14:03 2017
New Revision: 304470

URL: http://llvm.org/viewvc/llvm-project?rev=304470&view=rev
Log:
[CGDebugInfo] Finalize SubPrograms when we're done with them

`GenerateVarArgsThunk` in `CGVTables` clones a function before the frontend
is done emitting the compilation unit. Because of the way that DIBuilder
works, this means that the attached subprogram had incomplete (temporary)
metadata. Cloning such metadata is semantically disallowed, but happened
to work anyway due to bugs in the cloning logic. rL304226 attempted to fix
up that logic, but in the process exposed the incorrect API use here and
had to be reverted. To be able to fix this, I added a new method to
DIBuilder in rL304467, to allow finalizing a subprogram independently
of the entire compilation unit. Use that here, in preparation of re-applying
rL304226.

Reviewers: aprantl, dblaikie
Differential Revision: https://reviews.llvm.org/D33705

Modified:
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.h
cfe/trunk/lib/CodeGen/CodeGenFunction.cpp

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=304470&r1=304469&r2=304470&view=diff
==
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Thu Jun  1 16:14:03 2017
@@ -3263,7 +3263,7 @@ void CGDebugInfo::EmitInlineFunctionStar
 
 void CGDebugInfo::EmitInlineFunctionEnd(CGBuilderTy &Builder) {
   assert(CurInlinedAt && "unbalanced inline scope stack");
-  EmitFunctionEnd(Builder);
+  EmitFunctionEnd(Builder, nullptr);
   setInlinedAt(llvm::DebugLoc(CurInlinedAt).getInlinedAt());
 }
 
@@ -3332,7 +3332,7 @@ void CGDebugInfo::EmitLexicalBlockEnd(CG
   LexicalBlockStack.pop_back();
 }
 
-void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder) {
+void CGDebugInfo::EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn) {
   assert(!LexicalBlockStack.empty() && "Region stack mismatch, stack empty!");
   unsigned RCount = FnBeginRegionCount.back();
   assert(RCount <= LexicalBlockStack.size() && "Region stack mismatch");
@@ -3344,6 +3344,9 @@ void CGDebugInfo::EmitFunctionEnd(CGBuil
 LexicalBlockStack.pop_back();
   }
   FnBeginRegionCount.pop_back();
+
+  if (Fn && Fn->getSubprogram())
+DBuilder.finalizeSubprogram(Fn->getSubprogram());
 }
 
 llvm::DIType *CGDebugInfo::EmitTypeForVarWithBlocksAttr(const VarDecl *VD,

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=304470&r1=304469&r2=304470&view=diff
==
--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Thu Jun  1 16:14:03 2017
@@ -367,7 +367,7 @@ public:
   void EmitFunctionDecl(GlobalDecl GD, SourceLocation Loc, QualType FnType);
 
   /// Constructs the debug code for exiting a function.
-  void EmitFunctionEnd(CGBuilderTy &Builder);
+  void EmitFunctionEnd(CGBuilderTy &Builder, llvm::Function *Fn);
 
   /// Emit metadata to indicate the beginning of a new lexical block
   /// and push the block onto the stack.

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=304470&r1=304469&r2=304470&view=diff
==
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Jun  1 16:14:03 2017
@@ -348,7 +348,7 @@ void CodeGenFunction::FinishFunction(Sou
 
   // Emit debug descriptor for function end.
   if (CGDebugInfo *DI = getDebugInfo())
-DI->EmitFunctionEnd(Builder);
+DI->EmitFunctionEnd(Builder, CurFn);
 
   // Reset the debug location to that of the simple 'return' expression, if any
   // rather than that of the end of the function's scope '}'.


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r362855 - [analyzer] Add werror flag for analyzer warnings

2019-06-07 Thread Keno Fischer via cfe-commits
Author: kfischer
Date: Fri Jun  7 16:34:00 2019
New Revision: 362855

URL: http://llvm.org/viewvc/llvm-project?rev=362855&view=rev
Log:
[analyzer] Add werror flag for analyzer warnings

Summary:
We're using the clang static analyzer together with a number of
custom analyses in our CI system to ensure that certain invariants
are statiesfied for by the code every commit. Unfortunately, there
currently doesn't seem to be a good way to determine whether any
analyzer warnings were emitted, other than parsing clang's output
(or using scan-build, which then in turn parses clang's output).
As a simpler mechanism, simply add a `-analyzer-werror` flag to CC1
that causes the analyzer to emit its warnings as errors instead.
I briefly tried to have this be `Werror=analyzer` and make it go
through that machinery instead, but that seemed more trouble than
it was worth in terms of conflicting with options to the actual build
and special cases that would be required to circumvent the analyzers
usual attempts to quiet non-analyzer warnings. This is simple and it
works well.

Reviewed-By: NoQ, Szelethusw
Differential Revision: https://reviews.llvm.org/D62885

Modified:
cfe/trunk/include/clang/Driver/CC1Options.td
cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
cfe/trunk/lib/Frontend/CompilerInvocation.cpp
cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
cfe/trunk/test/Analysis/override-werror.c

Modified: cfe/trunk/include/clang/Driver/CC1Options.td
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/CC1Options.td?rev=362855&r1=362854&r2=362855&view=diff
==
--- cfe/trunk/include/clang/Driver/CC1Options.td (original)
+++ cfe/trunk/include/clang/Driver/CC1Options.td Fri Jun  7 16:34:00 2019
@@ -166,6 +166,9 @@ def analyzer_config_compatibility_mode :
 def analyzer_config_compatibility_mode_EQ : Joined<["-"], 
"analyzer-config-compatibility-mode=">,
   Alias;
 
+def analyzer_werror : Flag<["-"], "analyzer-werror">,
+  HelpText<"Emit analyzer results as errors rather than warnings">;
+
 
//===--===//
 // Migrator Options
 
//===--===//

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h?rev=362855&r1=362854&r2=362855&view=diff
==
--- cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h Fri Jun  7 
16:34:00 2019
@@ -245,6 +245,9 @@ public:
   /// strategy. We get better code coverage when retry is enabled.
   unsigned NoRetryExhausted : 1;
 
+  /// Emit analyzer warnings as errors.
+  unsigned AnalyzerWerror : 1;
+
   /// The inlining stack depth limit.
   // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls).
   unsigned InlineMaxStackDepth = 5;
@@ -297,7 +300,7 @@ public:
 AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false),
 eagerlyAssumeBinOpBifurcation(false), TrimGraph(false),
 visualizeExplodedGraphWithGraphViz(false), UnoptimizedCFG(false),
-PrintStats(false), NoRetryExhausted(false) {
+PrintStats(false), NoRetryExhausted(false), AnalyzerWerror(false) {
 llvm::sort(AnalyzerConfigCmdFlags);
   }
 

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=362855&r1=362854&r2=362855&view=diff
==
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Fri Jun  7 16:34:00 2019
@@ -309,6 +309,7 @@ static bool ParseAnalyzerArgs(AnalyzerOp
 Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
   Opts.DumpExplodedGraphTo = Args.getLastArgValue(OPT_analyzer_dump_egraph);
   Opts.NoRetryExhausted = Args.hasArg(OPT_analyzer_disable_retry_exhausted);
+  Opts.AnalyzerWerror = Args.hasArg(OPT_analyzer_werror);
   Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
   Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
   Opts.AnalyzeNestedBlocks =

Modified: cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp?rev=362855&r1=362854&r2=362855&view=diff
==
--- cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Frontend/AnalysisConsumer.cpp Fri Jun  7 
16:34:00 2019
@@ -83,10 +83,11 @@ void ento::createTextPathDiagnosticConsu
 namespace {
 cla

Re: [PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-09-26 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 72581.
loladiro added a comment.

back to _VSTD::forward, address review comments, add tests for non-empty 
deleter and unique_ptrs of arrays.


Repository:
  rL LLVM

https://reviews.llvm.org/D24372

Files:
  include/memory
  test/std/utilities/memory/unique.ptr/unique.ptr.runtime/constinit.pass.cpp
  test/std/utilities/memory/unique.ptr/unique.ptr.single/constinit.pass.cpp

Index: test/std/utilities/memory/unique.ptr/unique.ptr.single/constinit.pass.cpp
===
--- /dev/null
+++ test/std/utilities/memory/unique.ptr/unique.ptr.single/constinit.pass.cpp
@@ -0,0 +1,70 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03
+
+#include 
+#include 
+
+#ifndef _LIBCPP_SAFE_STATIC
+#define _LIBCPP_SAFE_STATIC
+#endif
+
+// This is basically std::default delete, except that it is not empty such that
+// we test a different code path in the implementation
+template  struct nonempty_delete {
+  uint32_t sentinel;
+  inline constexpr nonempty_delete() noexcept : sentinel(0xDEADBEEF) {}
+  template 
+  constexpr inline nonempty_delete(
+  const nonempty_delete &,
+  typename std::enable_if::value>::type * =
+  0) noexcept : sentinel(0xBAADF00D) {}
+  inline void operator()(Tp *ptr) const noexcept {
+assert(sentinel == 0xDEADBEEF || sentinel == 0xBAADF00D);
+delete ptr;
+  }
+};
+
+extern std::unique_ptr a;
+extern std::unique_ptr b;
+extern std::unique_ptr> c;
+extern std::unique_ptr> d;
+void *tramplea = std::memset(&a, 0xab, sizeof(a));
+void *trampleb = std::memset(&b, 0xab, sizeof(b));
+void *tramplec = std::memset(&a, 0xab, sizeof(c));
+void *trampled = std::memset(&b, 0xab, sizeof(d));
+_LIBCPP_SAFE_STATIC std::unique_ptr a;
+_LIBCPP_SAFE_STATIC std::unique_ptr b(nullptr);
+_LIBCPP_SAFE_STATIC std::unique_ptr> c;
+_LIBCPP_SAFE_STATIC std::unique_ptr> d(nullptr);
+
+int main() {
+  // Check that the initialization of 'a' was performed before the
+  // initialization of 'tramplea'.
+  for (size_t n = 0; n != sizeof(a); ++n)
+assert(reinterpret_cast(tramplea)[n] == 0xab);
+  // Check that the initialization of 'b' was performed before the
+  // initialization of 'trampleb'.
+  for (size_t n = 0; n != sizeof(b); ++n)
+assert(reinterpret_cast(trampleb)[n] == 0xab);
+  // Check that the initialization of 'c' was performed before the
+  // initialization of 'tramplec'.
+  for (size_t n = 0; n != sizeof(c); ++n)
+assert(reinterpret_cast(tramplec)[n] == 0xab);
+  // Check that the initialization of 'd' was performed before the
+  // initialization of 'trampled'.
+  for (size_t n = 0; n != sizeof(d); ++n)
+assert(reinterpret_cast(trampled)[n] == 0xab);
+  // Put a unique_ptr object back so that the global dtor is valid.
+  new (&a) std::unique_ptr;
+  new (&b) std::unique_ptr;
+  new (&c) std::unique_ptr>;
+  new (&d) std::unique_ptr>;
+}
Index: test/std/utilities/memory/unique.ptr/unique.ptr.runtime/constinit.pass.cpp
===
--- /dev/null
+++ test/std/utilities/memory/unique.ptr/unique.ptr.runtime/constinit.pass.cpp
@@ -0,0 +1,70 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03
+
+#include 
+#include 
+
+#ifndef _LIBCPP_SAFE_STATIC
+#define _LIBCPP_SAFE_STATIC
+#endif
+
+// This is basically std::default delete, except that it is not empty such that
+// we test a different code path in the implementation
+template  struct nonempty_delete {
+  uint32_t sentinel;
+  inline constexpr nonempty_delete() noexcept : sentinel(0xDEADBEEF) {}
+  template 
+  constexpr inline nonempty_delete(
+  const nonempty_delete &,
+  typename std::enable_if::value>::type * =
+  0) noexcept : sentinel(0xBAADF00D) {}
+  inline void operator()(Tp *ptr) const noexcept {
+assert(sentinel == 0xDEADBEEF || sentinel == 0xBAADF00D);
+delete[] ptr;
+  }
+};
+
+extern std::unique_ptr a;
+extern std::unique_ptr b;
+extern std::unique_ptr> c;
+extern std::unique_ptr> d;
+void *tramplea = std::memset(&a, 0xab, sizeof(a));
+void *trampleb = std::memset(&b, 0xab, sizeof(b));
+void *tramplec = std::memset(&a, 0xab, sizeof(c));
+void *trampled = std::memset(&b, 0xab, sizeof(d));
+_LIBCPP_SAFE_STATIC std::unique_ptr a;
+_LIBCPP_SAFE_STATIC std::unique_ptr b(nu

Re: [PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-09-27 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Before I commit this, I just realized

  __libcpp_compressed_pair_imp& operator=(const __libcpp_compressed_pair_imp& 
__p)
  _NOEXCEPT_(is_nothrow_copy_assignable<_T1>::value &&
 is_nothrow_copy_assignable<_T2>::value)
  {
  _T1::operator=(__p.first());
  __second_ = __p.second();
  return *this;
  }

is only constexpr in C++14, right?


Repository:
  rL LLVM

https://reviews.llvm.org/D24372



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-09-27 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 72712.
loladiro added a comment.

Some extra _AFTER_CXX11 that may be necessary - please double check me here, 
C++11 constexpr rules are not exactly my specialty ;).


Repository:
  rL LLVM

https://reviews.llvm.org/D24372

Files:
  include/memory
  test/std/utilities/memory/unique.ptr/unique.ptr.runtime/constinit.pass.cpp
  test/std/utilities/memory/unique.ptr/unique.ptr.single/constinit.pass.cpp

Index: test/std/utilities/memory/unique.ptr/unique.ptr.single/constinit.pass.cpp
===
--- /dev/null
+++ test/std/utilities/memory/unique.ptr/unique.ptr.single/constinit.pass.cpp
@@ -0,0 +1,70 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03
+
+#include 
+#include 
+
+#ifndef _LIBCPP_SAFE_STATIC
+#define _LIBCPP_SAFE_STATIC
+#endif
+
+// This is basically std::default delete, except that it is not empty such that
+// we test a different code path in the implementation
+template  struct nonempty_delete {
+  uint32_t sentinel;
+  inline constexpr nonempty_delete() noexcept : sentinel(0xDEADBEEF) {}
+  template 
+  constexpr inline nonempty_delete(
+  const nonempty_delete &,
+  typename std::enable_if::value>::type * =
+  0) noexcept : sentinel(0xBAADF00D) {}
+  inline void operator()(Tp *ptr) const noexcept {
+assert(sentinel == 0xDEADBEEF || sentinel == 0xBAADF00D);
+delete ptr;
+  }
+};
+
+extern std::unique_ptr a;
+extern std::unique_ptr b;
+extern std::unique_ptr> c;
+extern std::unique_ptr> d;
+void *tramplea = std::memset(&a, 0xab, sizeof(a));
+void *trampleb = std::memset(&b, 0xab, sizeof(b));
+void *tramplec = std::memset(&a, 0xab, sizeof(c));
+void *trampled = std::memset(&b, 0xab, sizeof(d));
+_LIBCPP_SAFE_STATIC std::unique_ptr a;
+_LIBCPP_SAFE_STATIC std::unique_ptr b(nullptr);
+_LIBCPP_SAFE_STATIC std::unique_ptr> c;
+_LIBCPP_SAFE_STATIC std::unique_ptr> d(nullptr);
+
+int main() {
+  // Check that the initialization of 'a' was performed before the
+  // initialization of 'tramplea'.
+  for (size_t n = 0; n != sizeof(a); ++n)
+assert(reinterpret_cast(tramplea)[n] == 0xab);
+  // Check that the initialization of 'b' was performed before the
+  // initialization of 'trampleb'.
+  for (size_t n = 0; n != sizeof(b); ++n)
+assert(reinterpret_cast(trampleb)[n] == 0xab);
+  // Check that the initialization of 'c' was performed before the
+  // initialization of 'tramplec'.
+  for (size_t n = 0; n != sizeof(c); ++n)
+assert(reinterpret_cast(tramplec)[n] == 0xab);
+  // Check that the initialization of 'd' was performed before the
+  // initialization of 'trampled'.
+  for (size_t n = 0; n != sizeof(d); ++n)
+assert(reinterpret_cast(trampled)[n] == 0xab);
+  // Put a unique_ptr object back so that the global dtor is valid.
+  new (&a) std::unique_ptr;
+  new (&b) std::unique_ptr;
+  new (&c) std::unique_ptr>;
+  new (&d) std::unique_ptr>;
+}
Index: test/std/utilities/memory/unique.ptr/unique.ptr.runtime/constinit.pass.cpp
===
--- /dev/null
+++ test/std/utilities/memory/unique.ptr/unique.ptr.runtime/constinit.pass.cpp
@@ -0,0 +1,70 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03
+
+#include 
+#include 
+
+#ifndef _LIBCPP_SAFE_STATIC
+#define _LIBCPP_SAFE_STATIC
+#endif
+
+// This is basically std::default delete, except that it is not empty such that
+// we test a different code path in the implementation
+template  struct nonempty_delete {
+  uint32_t sentinel;
+  inline constexpr nonempty_delete() noexcept : sentinel(0xDEADBEEF) {}
+  template 
+  constexpr inline nonempty_delete(
+  const nonempty_delete &,
+  typename std::enable_if::value>::type * =
+  0) noexcept : sentinel(0xBAADF00D) {}
+  inline void operator()(Tp *ptr) const noexcept {
+assert(sentinel == 0xDEADBEEF || sentinel == 0xBAADF00D);
+delete[] ptr;
+  }
+};
+
+extern std::unique_ptr a;
+extern std::unique_ptr b;
+extern std::unique_ptr> c;
+extern std::unique_ptr> d;
+void *tramplea = std::memset(&a, 0xab, sizeof(a));
+void *trampleb = std::memset(&b, 0xab, sizeof(b));
+void *tramplec = std::memset(&a, 0xab, sizeof(c));
+void *trampled = std::memset(&b, 0xab, sizeof(d));
+_LIBCPP_SAFE_STATIC std::unique_ptr a;
+_LIBCPP_SAFE_STA

[PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-10-06 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Bump, please do take another close look at the latest update, particularly with 
respecting to marking things constexpr that are not so in C++11.


Repository:
  rL LLVM

https://reviews.llvm.org/D24372



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D24371: Add diagnostics to require_constant_initialization

2016-09-08 Thread Keno Fischer via cfe-commits
loladiro created this revision.
loladiro added reviewers: EricWF, aaron.ballman, rsmith.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.

This hooks up the detailed diagnostics why constant initialization was not 
possible if require_constant_initialization reports an error. I have updated 
the test to account for the new notes.
Everything works fine, except that in C++11 mode we get:
```
error: 'note' diagnostics expected but not seen:
  File 
/data/llvm/tools/clang/test/SemaCXX/attr-require-constant-initialization.cpp 
Line 229 (directive at 
/data/llvm/tools/clang/test/SemaCXX/attr-require-constant-initialization.cpp:231):
 non-constexpr constructor 'NonLit' cannot be used in a constant expression
error: 'note' diagnostics seen but not expected:
  (frontend): non-literal type 'NonLit' cannot be used in a constant expression
```
This is because of an ImplicitValueInitExpr that gets passed into 
CheckLiteralType, but since ImplicitValueInitExpr doesn't have source 
information we get an invalid source location. I'm not really sure how to fix 
that (Is it possible to test for a note without source location?). Adding the 
proper source locations to ImplicitValueInitExpr seemed like a bigger 
undertaking than was warranted for this patch, so I'd appreciate guidance on 
how to proceed.

Repository:
  rL LLVM

https://reviews.llvm.org/D24371

Files:
  lib/Sema/SemaDecl.cpp
  test/SemaCXX/attr-require-constant-initialization.cpp

Index: test/SemaCXX/attr-require-constant-initialization.cpp
===
--- test/SemaCXX/attr-require-constant-initialization.cpp
+++ test/SemaCXX/attr-require-constant-initialization.cpp
@@ -7,9 +7,9 @@
 
 #define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}}
 
-int ReturnInt();
+int ReturnInt(); // expected-note 0+ {{declared here}}
 
-struct PODType {
+struct PODType { // expected-note 0+ {{declared here}}
   int value;
   int value2;
 };
@@ -20,17 +20,17 @@
 struct LitType {
   constexpr LitType() : value(0) {}
   constexpr LitType(int x) : value(x) {}
-  LitType(void *) : value(-1) {}
+  LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}}
   int value;
 };
 #endif
 
-struct NonLit {
+struct NonLit { // expected-note 0+ {{declared here}}
 #if __cplusplus >= 201402L
   constexpr NonLit() : value(0) {}
   constexpr NonLit(int x) : value(x) {}
 #else
-  NonLit() : value(0) {}
+  NonLit() : value(0) {}  // expected-note 0+ {{declared here}}
   NonLit(int x) : value(x) {}
 #endif
   NonLit(void *) : value(-1) {}
@@ -82,23 +82,44 @@
   const int non_global = 42;
   ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}}
   // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+  // expected-note@-3 {{reference to 'non_global' is not a constant expression}}
+  // expected-note@-5 {{declared here}}
+#else
+  // expected-note@-6 {{subexpression not valid in a constant expression}}
+#endif
   ATTR static const int &global_init = glvalue_int;
   ATTR static const int &temp_init = 42;
 }
 
 ATTR const int &temp_ref = 42;
 ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
+#else
+// expected-note@-5 {{subexpression not valid in a constant expression}}
+#endif
 ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a constant expression}}
+#else
+// expected-note@-5 {{subexpression not valid in a constant expression}}
+#endif
 
 #if __cplusplus >= 201103L
 ATTR const LitType &lit_temp_ref = 42;
 ATTR const int &subobj_ref = LitType{}.value;
 #endif
 
 ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note-re@-3 {{non-literal type '{{.*}}' cannot be used in a constant expression}}
+#else
+// expected-note@-5 {{subexpression not valid in a constant expression}}
+#endif
 
 struct TT1 {
   ATTR static const int &no_init;
@@ -116,6 +137,8 @@
 #if __cplusplus >= 201103L
 thread_local const int &TT1::tl_glvalue_init = glvalue_int;
 thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{reference to temporary is not a constant expression}}
+// expected

[PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-09-08 Thread Keno Fischer via cfe-commits
loladiro created this revision.
loladiro added reviewers: EricWF, mclow.lists.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.

Without this, unique_ptr is not constant initialized. I've added a test to that 
extent.
Unfortunately, I believe there's additional work required for C++11, since 
unique_ptr
uses std::forward internally which is not constexpr until C++14. Doing 
something about
that is not part of this patch. unique_ptr not being constant initialized is 
particularly problematic
because it is in libstdc++, so there's applications that rely on this behavior.

Repository:
  rL LLVM

https://reviews.llvm.org/D24372

Files:
  include/memory
  
test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/constinit.pass.cpp

Index: test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/constinit.pass.cpp
===
--- /dev/null
+++ test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/constinit.pass.cpp
@@ -0,0 +1,23 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03, c++11
+
+#include 
+#include 
+
+#ifndef _LIBCPP_SAFE_STATIC
+#define _LIBCPP_SAFE_STATIC
+#endif
+
+_LIBCPP_SAFE_STATIC static std::unique_ptr a;
+
+int main() {
+assert(a == nullptr);
+}
Index: include/memory
===
--- include/memory
+++ include/memory
@@ -2096,24 +2096,28 @@
 typedef const typename remove_reference<_T1>::type& _T1_const_reference;
 typedef const typename remove_reference<_T2>::type& _T2_const_reference;
 
-_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() : __first_(), __second_() {}
-_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T1_param __t1)
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+__libcpp_compressed_pair_imp() : __first_(), __second_() {}
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+explicit __libcpp_compressed_pair_imp(_T1_param __t1)
 : __first_(_VSTD::forward<_T1_param>(__t1)), __second_() {}
-_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T2_param __t2)
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+explicit __libcpp_compressed_pair_imp(_T2_param __t2)
 : __first_(), __second_(_VSTD::forward<_T2_param>(__t2)) {}
-_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2)
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+__libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2)
 : __first_(_VSTD::forward<_T1_param>(__t1)), __second_(_VSTD::forward<_T2_param>(__t2)) {}
 
 #if defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
 
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 __libcpp_compressed_pair_imp(const __libcpp_compressed_pair_imp& __p)
 _NOEXCEPT_(is_nothrow_copy_constructible<_T1>::value &&
is_nothrow_copy_constructible<_T2>::value)
 : __first_(__p.first()),
   __second_(__p.second()) {}
 
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 __libcpp_compressed_pair_imp& operator=(const __libcpp_compressed_pair_imp& __p)
 _NOEXCEPT_(is_nothrow_copy_assignable<_T1>::value &&
is_nothrow_copy_assignable<_T2>::value)
@@ -2123,14 +2127,14 @@
 return *this;
 }
 
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 __libcpp_compressed_pair_imp(__libcpp_compressed_pair_imp&& __p)
 _NOEXCEPT_(is_nothrow_move_constructible<_T1>::value &&
is_nothrow_move_constructible<_T2>::value)
 : __first_(_VSTD::forward<_T1>(__p.first())),
   __second_(_VSTD::forward<_T2>(__p.second())) {}
 
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 __libcpp_compressed_pair_imp& operator=(__libcpp_compressed_pair_imp&& __p)
 _NOEXCEPT_(is_nothrow_move_assignable<_T1>::value &&
is_nothrow_move_assignable<_T2>::value)
@@ -2145,7 +2149,7 @@
 #ifndef _LIBCPP_HAS_NO_VARIADICS
 
 template 
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 __libcpp_compressed_pair_imp(piecewise_construct_t __pc,
  tuple<_Args1...> __first_args,
  tuple<_Args2...> __second_args,
@@ -2189,23 +2193,27 @@
 typedef const _T1&_T1_co

Re: [PATCH] D24371: Add diagnostics to require_constant_initialization

2016-09-09 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: lib/Sema/SemaDecl.cpp:10535-10538
@@ -10534,1 +10534,6 @@
   << attr->getRange();
+APValue Value;
+SmallVector Notes;
+cast(var->ensureEvaluatedStmt()->Value)->EvaluateAsInitializer(
+  Value, getASTContext(), var, Notes);
+for (auto &it : Notes)

rsmith wrote:
> Can you capture the diagnostics from `checkInitIsICE` instead of recomputing 
> them here? (It looks straightforward to add an overload that takes a vector 
> of notes.) In the non-C++11 case, you can produce a note pointing to 
> `CacheCulprit` instead.
The problem is that the result of checking is cached internally and the 
diagnostics are only produced the first time. I don't think it's necessarily 
guaranteed that the above `checkInitIsICE` is the first such call (unless you 
can see such a reason). 


Repository:
  rL LLVM

https://reviews.llvm.org/D24371



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24371: Add diagnostics to require_constant_initialization

2016-09-09 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 70915.
loladiro added a comment.

Address review comments:

- Disable C++11 test that lacks source locations
- Use CacheCulprit to give diagnostics for < C++11


Repository:
  rL LLVM

https://reviews.llvm.org/D24371

Files:
  lib/Sema/SemaDecl.cpp
  test/SemaCXX/attr-require-constant-initialization.cpp

Index: test/SemaCXX/attr-require-constant-initialization.cpp
===
--- test/SemaCXX/attr-require-constant-initialization.cpp
+++ test/SemaCXX/attr-require-constant-initialization.cpp
@@ -7,9 +7,9 @@
 
 #define ATTR __attribute__((require_constant_initialization)) // expected-note 0+ {{expanded from macro}}
 
-int ReturnInt();
+int ReturnInt(); // expected-note 0+ {{declared here}}
 
-struct PODType {
+struct PODType { // expected-note 0+ {{declared here}}
   int value;
   int value2;
 };
@@ -20,20 +20,20 @@
 struct LitType {
   constexpr LitType() : value(0) {}
   constexpr LitType(int x) : value(x) {}
-  LitType(void *) : value(-1) {}
+  LitType(void *) : value(-1) {} // expected-note 0+ {{declared here}}
   int value;
 };
 #endif
 
-struct NonLit {
+struct NonLit { // expected-note 0+ {{declared here}}
 #if __cplusplus >= 201402L
   constexpr NonLit() : value(0) {}
   constexpr NonLit(int x) : value(x) {}
 #else
-  NonLit() : value(0) {}
+  NonLit() : value(0) {} // expected-note 0+ {{declared here}}
   NonLit(int x) : value(x) {}
 #endif
-  NonLit(void *) : value(-1) {}
+  NonLit(void *) : value(-1) {} // expected-note 0+ {{declared here}}
   ~NonLit() {}
   int value;
 };
@@ -82,23 +82,44 @@
   const int non_global = 42;
   ATTR static const int &local_init = non_global; // expected-error {{variable does not have a constant initializer}}
   // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{reference to 'non_global' is not a constant expression}}
+// expected-note@-5 {{declared here}}
+#else
+// expected-note@-6 {{subexpression not valid in a constant expression}}
+#endif
   ATTR static const int &global_init = glvalue_int;
   ATTR static const int &temp_init = 42;
 }
 
 ATTR const int &temp_ref = 42;
 ATTR const int &temp_ref2 = ReturnInt(); // expected-error {{variable does not have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
+#else
+// expected-note@-5 {{subexpression not valid in a constant expression}}
+#endif
 ATTR const NonLit &nl_temp_ref = 42; // expected-error {{variable does not have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{non-literal type 'const NonLit' cannot be used in a constant expression}}
+#else
+// expected-note@-5 {{subexpression not valid in a constant expression}}
+#endif
 
 #if __cplusplus >= 201103L
 ATTR const LitType &lit_temp_ref = 42;
 ATTR const int &subobj_ref = LitType{}.value;
 #endif
 
 ATTR const int &nl_subobj_ref = NonLit().value; // expected-error {{variable does not have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note-re@-3 {{non-literal type '{{.*}}' cannot be used in a constant expression}}
+#else
+// expected-note@-5 {{subexpression not valid in a constant expression}}
+#endif
 
 struct TT1 {
   ATTR static const int &no_init;
@@ -116,6 +137,8 @@
 #if __cplusplus >= 201103L
 thread_local const int &TT1::tl_glvalue_init = glvalue_int;
 thread_local const int &TT1::tl_temp_init = 42; // expected-error {{variable does not have a constant initializer}}
+// expected-note@-1 {{reference to temporary is not a constant expression}}
+// expected-note@-2 {{temporary created here}}
 #endif
 
 // [basic.start.static]p2.2
@@ -129,17 +152,25 @@
 #else
   ATTR static PODType pod; // expected-error {{variable does not have a constant initializer}}
 // expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+// expected-note@-2 {{non-constexpr constructor 'PODType' cannot be used in a constant expression}}
 #endif
   ATTR static PODType pot2 = {ReturnInt()}; // expected-error {{variable does not have a constant initializer}}
-// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+// expected-note@-1 {{required by 'require_constant_initializer' attribute here}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{non-constexpr function 'ReturnInt' cannot be used in a constant expression}}
+#else
+// expected-note@-5 {{subexpression not valid in a constant expression}}
+#endif
 
 #if __cplusplus >= 201103L
   constexpr LitType l;
   ATTR static LitType static_lit = l;
   ATTR static LitType static_lit

Re: [PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-09-13 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Small bump here. Is it possible to rewrite these without std::forward, so we 
can have the const-initialization behavior on C++11 (or is there are different 
solution?).


Repository:
  rL LLVM

https://reviews.llvm.org/D24372



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-09-13 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: include/memory:2137
@@ -2132,3 +2136,3 @@
 
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 __libcpp_compressed_pair_imp& operator=(__libcpp_compressed_pair_imp&& __p)

mclow.lists wrote:
> loladiro wrote:
> > mclow.lists wrote:
> > > Have you tested this on C++11?
> > > I suspect that some of these need to be `_LIBCPP_CONSTEXPR_AFTER_CXX11`
> > Well, as I mentioned there are other problems on C++11, namely forward not 
> > being constexpr (so even the simple constructors below can't be constant 
> > initialized in C++11). I would REALLY like for unique_ptr to be constant 
> > initialized even in C++11 mode. I feel like arguably the standard requires 
> > it by marking the constructor `constexpr`.
> One way to deal with that is to define a call `__forward()` that is the same 
> as `forward()` except that it's constexpr in C++11, and have compressed_pair 
> call that.
> 
I was worried that something in the definition of forward required C++14 
constexpr semantics? Is that not the case. If so this sounds like a good 
solution, and I can update the patch accordingly.


Repository:
  rL LLVM

https://reviews.llvm.org/D24372



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-09-15 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 71528.
loladiro added a comment.

Add private copy of forward (__forward) that is constexpr even in C++11 mode, 
use test suggested by @rsmith


Repository:
  rL LLVM

https://reviews.llvm.org/D24372

Files:
  include/memory
  
test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/constinit.pass.cpp

Index: test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/constinit.pass.cpp
===
--- /dev/null
+++ test/std/utilities/memory/unique.ptr/unique.ptr.runtime/unique.ptr.runtime.ctor/constinit.pass.cpp
@@ -0,0 +1,36 @@
+//===--===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===--===//
+
+// UNSUPPORTED: c++98, c++03
+
+#include 
+#include 
+
+#ifndef _LIBCPP_SAFE_STATIC
+#define _LIBCPP_SAFE_STATIC
+#endif
+
+extern std::unique_ptr a;
+extern std::unique_ptr b;
+void *tramplea = std::memset(&a, 0xab, sizeof(a));
+void *trampleb = std::memset(&b, 0xab, sizeof(b));
+_LIBCPP_SAFE_STATIC std::unique_ptr a;
+_LIBCPP_SAFE_STATIC std::unique_ptr b(nullptr);
+
+int main() {
+// Check that the initialization of 'a' was performed before the initialization of 'tramplea'.
+for (size_t n = 0; n != sizeof(a); ++n)
+  assert(reinterpret_cast(tramplea)[n] == 0xab);
+// Check that the initialization of 'b' was performed before the initialization of 'trampleb'.
+for (size_t n = 0; n != sizeof(b); ++n)
+  assert(reinterpret_cast(trampleb)[n] == 0xab);
+// Put a unique_ptr object back so that the global dtor is valid.
+new (&a) std::unique_ptr;
+new (&b) std::unique_ptr;
+}
Index: include/memory
===
--- include/memory
+++ include/memory
@@ -2053,6 +2053,26 @@
 typedef void element_type;
 };
 
+// Private copy of forward, for use only in this file, which is constexpr even
+// in C++11
+template 
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+_Tp&&
+__forward(typename remove_reference<_Tp>::type& __t) _NOEXCEPT
+{
+return static_cast<_Tp&&>(__t);
+}
+
+template 
+inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+_Tp&&
+__forward(typename remove_reference<_Tp>::type&& __t) _NOEXCEPT
+{
+static_assert(!is_lvalue_reference<_Tp>::value,
+  "Can not forward an rvalue as an lvalue.");
+return static_cast<_Tp&&>(__t);
+}
+
 template ::type,
  typename remove_cv<_T2>::type>::value,
 bool = is_empty<_T1>::value
@@ -2096,24 +2116,28 @@
 typedef const typename remove_reference<_T1>::type& _T1_const_reference;
 typedef const typename remove_reference<_T2>::type& _T2_const_reference;
 
-_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp() : __first_(), __second_() {}
-_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T1_param __t1)
-: __first_(_VSTD::forward<_T1_param>(__t1)), __second_() {}
-_LIBCPP_INLINE_VISIBILITY explicit __libcpp_compressed_pair_imp(_T2_param __t2)
-: __first_(), __second_(_VSTD::forward<_T2_param>(__t2)) {}
-_LIBCPP_INLINE_VISIBILITY __libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2)
-: __first_(_VSTD::forward<_T1_param>(__t1)), __second_(_VSTD::forward<_T2_param>(__t2)) {}
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+__libcpp_compressed_pair_imp() : __first_(), __second_() {}
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+explicit __libcpp_compressed_pair_imp(_T1_param __t1)
+: __first_(__forward<_T1_param>(__t1)), __second_() {}
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+explicit __libcpp_compressed_pair_imp(_T2_param __t2)
+: __first_(), __second_(__forward<_T2_param>(__t2)) {}
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
+__libcpp_compressed_pair_imp(_T1_param __t1, _T2_param __t2)
+: __first_(__forward<_T1_param>(__t1)), __second_(__forward<_T2_param>(__t2)) {}
 
 #if defined(_LIBCPP_HAS_NO_DEFAULTED_FUNCTIONS) && !defined(_LIBCPP_HAS_NO_RVALUE_REFERENCES)
 
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 __libcpp_compressed_pair_imp(const __libcpp_compressed_pair_imp& __p)
 _NOEXCEPT_(is_nothrow_copy_constructible<_T1>::value &&
is_nothrow_copy_constructible<_T2>::value)
 : __first_(__p.first()),
   __second_(__p.second()) {}
 
-_LIBCPP_INLINE_VISIBILITY
+_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
 __libcpp_compressed_pair_imp& operator=(const __libcpp_compressed_pair_imp& __p)
 _NOEXCEPT_(is_nothrow_copy_assignable<_T1

[PATCH] D13330: Implement __attribute__((unique_instantiation))

2016-10-27 Thread Keno Fischer via cfe-commits
loladiro added a comment.

I came across a situation again where this would be useful to have. I know this 
was approved, but looking it looks like I wanted @majnemer to have another look.


https://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2016-10-27 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Since this was approved, I'll rebase and commit.


Repository:
  rL LLVM

https://reviews.llvm.org/D13419



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D24372: [libcxx] Sprinkle constexpr over compressed_pair

2016-10-27 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Ok then, will commit.


Repository:
  rL LLVM

https://reviews.llvm.org/D24372



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2016-10-27 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 76094.
loladiro added a comment.

Rebased patch


Repository:
  rL LLVM

https://reviews.llvm.org/D13419

Files:
  lib/AST/Decl.cpp
  lib/AST/DeclCXX.cpp
  test/CodeGenCXX/visibility.cpp

Index: test/CodeGenCXX/visibility.cpp
===
--- test/CodeGenCXX/visibility.cpp
+++ test/CodeGenCXX/visibility.cpp
@@ -1317,3 +1317,59 @@
   // CHECK-LABEL: define void @_ZN6test693foo1fEv
   // CHECK-HIDDEN-LABEL: define hidden void @_ZN6test693foo1fEv
 }
+
+namespace test70 {
+template 
+class foo {
+public:
+  T x;
+  template 
+  HIDDEN S AddS(S);
+  template 
+  class HIDDEN barS {
+  public:
+static S AddS2(foo x, S);
+  };
+  template 
+  class HIDDEN barZ {
+  public:
+template 
+static S AddSZ(foo x, S, Z);
+  };
+};
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+template 
+template 
+HIDDEN S foo::AddS(S y) {
+  return ((S)x) + y;
+}
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+template 
+template 
+HIDDEN S foo::barS::AddS2(foo x, S y) {
+  return ((S)x.x) + y;
+}
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+template 
+template 
+template 
+HIDDEN S foo::barZ::AddSZ(foo x, S y, Z z) {
+  return ((S)x.x) + y + ((S)z);
+}
+
+extern template struct foo;
+template struct foo;
+
+void f() {
+  auto var = foo{5};
+  auto bar = var.AddS((long long)3);
+  auto bar2 = decltype(var)::barS::AddS2(var, 3);
+  auto bar3 = decltype(var)::barZ::AddSZ(var, 3, (char)0);
+}
+}
Index: lib/AST/DeclCXX.cpp
===
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1346,17 +1346,19 @@
   if (auto *TD = dyn_cast(this)) {
 auto From = TD->getInstantiatedFrom();
 if (auto *CTD = From.dyn_cast()) {
-  while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
-if (NewCTD->isMemberSpecialization())
+  while (!CTD->isMemberSpecialization()) {
+auto *NewCTD = CTD->getInstantiatedFromMemberTemplate();
+if (!NewCTD)
   break;
 CTD = NewCTD;
   }
   return CTD->getTemplatedDecl()->getDefinition();
 }
 if (auto *CTPSD =
 From.dyn_cast()) {
-  while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
-if (NewCTPSD->isMemberSpecialization())
+  while (!CTPSD->isMemberSpecialization()) {
+auto *NewCTPSD = CTPSD->getInstantiatedFromMember();
+if (!NewCTPSD)
   break;
 CTPSD = NewCTPSD;
   }
Index: lib/AST/Decl.cpp
===
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1052,7 +1052,10 @@
   // If this is a member class of a specialization of a class template
   // and the corresponding decl has explicit visibility, use that.
   if (const auto *RD = dyn_cast(ND)) {
-CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+const CXXRecordDecl *InstantiatedFrom =
+RD->getTemplateInstantiationPattern();
+if (!InstantiatedFrom)
+  InstantiatedFrom = RD->getInstantiatedFromMemberClass();
 if (InstantiatedFrom)
   return getVisibilityOf(InstantiatedFrom, kind);
   }
@@ -1086,16 +1089,13 @@
   }
   // Also handle function template specializations.
   if (const auto *fn = dyn_cast(ND)) {
-// If the function is a specialization of a template with an
-// explicit visibility attribute, use that.
-if (FunctionTemplateSpecializationInfo *templateInfo
-  = fn->getTemplateSpecializationInfo())
-  return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
- kind);
+// If the function is a template specialization or a member of
+// a specialized class template and the corresponding decl has
+// explicit visibility, use that.
+FunctionDecl *InstantiatedFrom = fn->getTemplateInstantiationPattern();
+if (!InstantiatedFrom)
+  InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
 
-// If the function is a member of a specialization of a class template
-// and the corresponding decl has explicit visibility, use that.
-FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
 if (InstantiatedFrom)
   return getVisibilityOf(InstantiatedFrom, kind);
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2016-10-27 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Hmm, the rebased version of this introduces new errors in 
`test/Modules/cxx-templates.cpp`. That test didn't exist when I wrote this code 
and I'm not familiar with templates. @rsmith could you take a look, error is:

  error: 'error' diagnostics seen but not expected:
File /data/keno/llvm/tools/clang/test/Modules/cxx-templates.cpp Line 202: 
definition of 'nested_cls_t' must be imported from module 
'cxx_templates_common.unimported' before it is required
File /data/keno/llvm/tools/clang/test/Modules/cxx-templates.cpp Line 202: 
definition of 'nested_cls_t' must be imported from module 
'cxx_templates_common.unimported' before it is required


Repository:
  rL LLVM

https://reviews.llvm.org/D13419



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13330: Implement __attribute__((unique_instantiation))

2016-10-27 Thread Keno Fischer via cfe-commits
loladiro set the repository for this revision to rL LLVM.
loladiro updated this revision to Diff 76102.
loladiro added a comment.

Rebased on current master.


Repository:
  rL LLVM

https://reviews.llvm.org/D13330

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  include/clang/Sema/Sema.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2662,6 +2662,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang -cc1 -std=c++14 -fsyntax-only -verify %s
+
+// Correct usage
+template 
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+// Usages on non-templates
+float __attribute__((unique_instantiation)) notpi(2.71828182845904523536028747135); // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+struct __attribute__((unique_instantiation)) bar {};// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+void __attribute__((unique_instantiation)) func() {}// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+// Usages that violate one of the conditions required conditions
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+T pi1 = T(3.1415926535897932385);
+template __attribute__((unique_instantiation)) float pi1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct __attribute__((unique_instantiation(16))) foo6; // expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang -std=c++14 -emit-llvm -c -S -o - %s | FileCheck %s
+
+// CHECK: @_Z2piIfE = global float
+// CHECK-NOT: @_Z2piIfE = weak_odr global float
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) f

[PATCH] D13330: Implement __attribute__((unique_instantiation))

2016-10-27 Thread Keno Fischer via cfe-commits
loladiro added a comment.

I found a bug in this which I need to fix, but while I'm at it, in doing more 
testing on this, I came across the following corner case:

  template 
  struct static_separate_template {
  typedef T element;
  static T *a_static_field;
  };
  extern template struct __attribute__((unique_instantiation)) 
static_separate_template;
  template struct __attribute__((unique_instantiation)) 
static_separate_template;
  extern template struct __attribute__((unique_instantiation)) 
static_separate_template;
  template struct __attribute__((unique_instantiation)) 
static_separate_template;
  
  template  typename static_separate_template::element 
*static_separate_template::a_static_field = nullptr;
  template int * __attribute__((unique_instantiation)) 
static_separate_template::a_static_field;
  template char * static_separate_template::a_static_field; // 
expected-error{{'unique_instantiation' attribute must be specified for all 
declarations and definitions of this explicit template instantiation}}

How should this be handled? I indicated my inclination in the comment, but I'm 
open to alternative suggestions.


Repository:
  rL LLVM

https://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13330: Implement __attribute__((unique_instantiation))

2016-10-28 Thread Keno Fischer via cfe-commits
loladiro added a comment.

I meant 
`template __attribute__((unique_instantiation)) int * 
static_separate_template::a_static_field;`
of course, though we probably need a better diagnostic for the other spelling 
(which applies the attribute to the static_separate_template). I'll look 
into adding a diagnostic.


Repository:
  rL LLVM

https://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13330: Implement __attribute__((unique_instantiation))

2016-10-28 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 76256.
loladiro added a comment.

Fix for the corner case I found and add it as a test.


Repository:
  rL LLVM

https://reviews.llvm.org/D13330

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  include/clang/Sema/Sema.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2662,6 +2662,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang -cc1 -std=c++14 -fsyntax-only -verify %s
+
+// Correct usage
+template 
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+// Usages on non-templates
+float __attribute__((unique_instantiation)) notpi(2.71828182845904523536028747135); // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+struct __attribute__((unique_instantiation)) bar {};// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+void __attribute__((unique_instantiation)) func() {}// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+// Usages that violate one of the conditions required conditions
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+T pi1 = T(3.1415926535897932385);
+template __attribute__((unique_instantiation)) float pi1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct __attribute__((unique_instantiation(16))) foo6; // expected-error{{'unique_instantiation' attribute takes no arguments}}
+
+template 
+struct static_separate_template {
+typedef T element;
+static T *a_static_field;
+};
+extern template struct __attribute__((unique_instantiation)) static_separate_template;
+template struct __attribute__((unique_instantiation)) static_separate_template;
+extern template struct __attribute__((unique_instantiation)) static_separate_template; // expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) static_separate_template;
+
+template  typename static_se

[PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2016-10-28 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 76257.
loladiro added a comment.

Add the expected-error annotation


Repository:
  rL LLVM

https://reviews.llvm.org/D13419

Files:
  lib/AST/Decl.cpp
  lib/AST/DeclCXX.cpp
  test/CodeGenCXX/visibility.cpp
  test/Modules/cxx-templates.cpp

Index: test/Modules/cxx-templates.cpp
===
--- test/Modules/cxx-templates.cpp
+++ test/Modules/cxx-templates.cpp
@@ -199,7 +199,7 @@
 cls uk4; // expected-error 1+{{partial specialization of 'cls' must be imported}} expected-error 1+{{definition of}}
 cls::nested_cls unk1; // expected-error 1+{{explicit specialization of 'nested_cls' must be imported}} expected-error 1+{{definition of}}
 cls::nested_cls_t unk2; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}
-cls::nested_cls_t unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}}
+cls::nested_cls_t unk3; // expected-error 1+{{explicit specialization of 'nested_cls_t' must be imported}} expected-error 1+{{definition of}}
 
 // For enums, uses that would trigger instantiations of definitions are not
 // allowed.
Index: test/CodeGenCXX/visibility.cpp
===
--- test/CodeGenCXX/visibility.cpp
+++ test/CodeGenCXX/visibility.cpp
@@ -1317,3 +1317,59 @@
   // CHECK-LABEL: define void @_ZN6test693foo1fEv
   // CHECK-HIDDEN-LABEL: define hidden void @_ZN6test693foo1fEv
 }
+
+namespace test70 {
+template 
+class foo {
+public:
+  T x;
+  template 
+  HIDDEN S AddS(S);
+  template 
+  class HIDDEN barS {
+  public:
+static S AddS2(foo x, S);
+  };
+  template 
+  class HIDDEN barZ {
+  public:
+template 
+static S AddSZ(foo x, S, Z);
+  };
+};
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+template 
+template 
+HIDDEN S foo::AddS(S y) {
+  return ((S)x) + y;
+}
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+template 
+template 
+HIDDEN S foo::barS::AddS2(foo x, S y) {
+  return ((S)x.x) + y;
+}
+
+// CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+// CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+template 
+template 
+template 
+HIDDEN S foo::barZ::AddSZ(foo x, S y, Z z) {
+  return ((S)x.x) + y + ((S)z);
+}
+
+extern template struct foo;
+template struct foo;
+
+void f() {
+  auto var = foo{5};
+  auto bar = var.AddS((long long)3);
+  auto bar2 = decltype(var)::barS::AddS2(var, 3);
+  auto bar3 = decltype(var)::barZ::AddSZ(var, 3, (char)0);
+}
+}
Index: lib/AST/DeclCXX.cpp
===
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1346,17 +1346,19 @@
   if (auto *TD = dyn_cast(this)) {
 auto From = TD->getInstantiatedFrom();
 if (auto *CTD = From.dyn_cast()) {
-  while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
-if (NewCTD->isMemberSpecialization())
+  while (!CTD->isMemberSpecialization()) {
+auto *NewCTD = CTD->getInstantiatedFromMemberTemplate();
+if (!NewCTD)
   break;
 CTD = NewCTD;
   }
   return CTD->getTemplatedDecl()->getDefinition();
 }
 if (auto *CTPSD =
 From.dyn_cast()) {
-  while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
-if (NewCTPSD->isMemberSpecialization())
+  while (!CTPSD->isMemberSpecialization()) {
+auto *NewCTPSD = CTPSD->getInstantiatedFromMember();
+if (!NewCTPSD)
   break;
 CTPSD = NewCTPSD;
   }
Index: lib/AST/Decl.cpp
===
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1052,7 +1052,10 @@
   // If this is a member class of a specialization of a class template
   // and the corresponding decl has explicit visibility, use that.
   if (const auto *RD = dyn_cast(ND)) {
-CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+const CXXRecordDecl *InstantiatedFrom =
+RD->getTemplateInstantiationPattern();
+if (!InstantiatedFrom)
+  InstantiatedFrom = RD->getInstantiatedFromMemberClass();
 if (InstantiatedFrom)
   return getVisibilityOf(InstantiatedFrom, kind);
   }
@@ -1086,16 +1089,13 @@
   }
   // Also handle function template specializations.
   if (const auto *fn = dyn_cast(ND)) {
-// If the function is a specialization of a template with an
-// explicit visibility attribute, use that.
-if (FunctionTemplateSpecializationInfo *templateInfo
-  = fn->getTemplateSpecializationInfo())
-  return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
-   

[PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2016-10-28 Thread Keno Fischer via cfe-commits
loladiro added inline comments.



Comment at: lib/AST/DeclCXX.cpp:1349-1354
+  while (!CTD->isMemberSpecialization()) {
+auto *NewCTD = CTD->getInstantiatedFromMemberTemplate();
+if (!NewCTD)
   break;
 CTD = NewCTD;
   }

rsmith wrote:
> The same bug exists in `VarDecl::getTemplateInstantiationPattern`; can you 
> fix it there too?
Do you have a test case that shows a problem with the current definition of 
that function? Would like to include it if possible. I tried cooking one up, 
but wasn't particularly successful.


Repository:
  rL LLVM

https://reviews.llvm.org/D13419



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13330: Implement __attribute__((unique_instantiation))

2016-10-28 Thread Keno Fischer via cfe-commits
loladiro planned changes to this revision.
loladiro added a comment.

Thanks for the review! Sorry, it's been a while since I wrote this code, so I'm 
not fluent in all the details, but I've replied below. I am not particularly 
partial to the name, so whatever you feel is best is ok with me.




Comment at: include/clang/Basic/AttrDocs.td:2321-2323
+When the unique_instantiation attribute is specified on an explicit template
+instantiation, the compiler is given license to emit strong symbols for
+this specific explicit template instantiation.

rsmith wrote:
> The primary description of the attribute should specify what it means, not 
> the consequences of that meaning. In this case, the meaning is that the 
> programmer is guaranteeing to the compiler that an explicit instantiation 
> precedes all implicit instantiations, and the consequence is that we can use 
> strong symbols.
Ok, sounds good.



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:2456
+def err_unique_instantiation_not_previous : Error<
+  "'unique_instantiation' attribute must be specified for all declarations and 
definitions of this explicit template instantiation">;
 

rsmith wrote:
> loladiro wrote:
> > aaron.ballman wrote:
> > > > They are checking for two different conditions in the spec. One 
> > > > requires that all explicit template instantiations with this attribute 
> > > > have a declaration, the other that every declaration/definition has the 
> > > > attribute.
> > > 
> > > Okay, I see now what this diagnostic is attempting to convey. I think it 
> > > should read:
> > > ```
> > > def err_unique_instantiation_no_declaration : Error<
> > >   "'unique_instantiation' attribute on an explicit instantiation requires 
> > > a previous explicit instantiation declaration">;
> > > ```
> > Sounds good.
> This seems like an unnecessarily-strict rule to me. I don't see a reason to 
> disallow:
> ```
> // in header
> extern template struct __attribute__((whatever_its_called)) X;
> ```
> ```
> // in source file
> template struct X;
> ```
> There doesn't appear to be any safety or correctness concern here. In 
> general, it seems like the attribute is only promising that the explicit 
> instantiation declaration precedes any other instantiation, so the only 
> necessary rule would seem to be: if the attribute is present on any explicit 
> instantiation, the first point of instantiation must be an explicit 
> instantiation declaration that has the attribute.
While I didn't write the rules (just implemented them from the original 
proposal), I like the requirement from the point of view of making sure that 
the explicit instantiation declaration doesn't accidentally get deleted. Those 
declarations are somewhat odd in that they can be deleted without any semantic 
loss in functionality (just larger code size/more work for the linker) in the 
absence of this attribute. However, with this attribute, deleting the 
declaration would cause a subtle, perhaps hard to track down semantic change, 
so I like requiring people to be explicit. 



Comment at: lib/Sema/SemaDecl.cpp:2398-2399
+  // template declarations. In clang getDefinition() will get the
+  // ClassTemplateSpecializationDecl associated with the class template
+  // declaration, so we'd give incorrect warnings here.
+  if (auto *CTSD = dyn_cast(New)) {

rsmith wrote:
> I have no idea what you mean by this. Did you mean "associated with the 
> explicit instantiation declaration" or something like that?
Yes, I believe that is what I meant. It's been a while since I wrote this code, 
but I believe that all I'm trying to say here is that explicit instantiation 
declarations/definitions are allowed to add attributes after a definition, even 
though that is not normally allowed.



Comment at: lib/Sema/SemaDeclAttr.cpp:5400
+  if (!CTSD->getPreviousDecl())
+S.Diag(Attr.getLoc(), diag::err_unique_instantiation_no_declaration);
+}

rsmith wrote:
> Why is this rule only applied to explicit instantiations of class templates, 
> and not to function or variable templates?
I don't remember precisely, but I believe (at least when I wrote the patch) 
that those prior explicit instantiation declarations did not leave an AST node 
that I could check for.



Comment at: lib/Sema/SemaDeclCXX.cpp:5666-5685
+/// \brief Check if the new class needs a unique instantiation attribute
+/// based on whether its containing function or class has it
+void Sema::checkClassLevelUniqueInstantiation(CXXRecordDecl *Record) {
+  Decl *D = Record;
+  if (!D || D->hasAttr())
+return;
+  while (DeclContext *DC = D ? D->getDeclContext() : nullptr) {

rsmith wrote:
> I don't think this is the right way to handle this case. Note that an 
> explicit instantiation declaration/definition for a class is only an explicit 
> instantiation of those m

[PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2016-10-30 Thread Keno Fischer via cfe-commits
loladiro added a comment.

I'm really out of my depth in this code, but it looks like that test case is 
triggering the one code path in that function that is actually correct. Could 
you adjust it to trigger the code path behind the first if statement?


Repository:
  rL LLVM

https://reviews.llvm.org/D13419



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D12854: [SourceManager] Support buffers that are not null-terminated

2015-09-14 Thread Keno Fischer via cfe-commits
loladiro created this revision.
loladiro added a reviewer: bkramer.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.

I feed custom buffers to clang, and since the buffers store an explicit length, 
I did not think to null-terminate them.
However, this causes clang to run out-of-bounds in certain situations in 
`ComputeLineNumbers`. Since under certain
situations `ComputeLineNumbers` does look at the given bounds, I figured the 
proper solution was to always check the
buffer for EOF. Please let me know if I missed something and this was intended.

Repository:
  rL LLVM

http://reviews.llvm.org/D12854

Files:
  lib/Basic/SourceManager.cpp

Index: lib/Basic/SourceManager.cpp
===
--- lib/Basic/SourceManager.cpp
+++ lib/Basic/SourceManager.cpp
@@ -1227,7 +1227,7 @@
 
 // First fix up the alignment to 16 bytes.
 while (((uintptr_t)NextBuf & 0xF) != 0) {
-  if (*NextBuf == '\n' || *NextBuf == '\r' || *NextBuf == '\0')
+  if (*NextBuf == '\n' || *NextBuf == '\r' || *NextBuf == '\0' || NextBuf 
== End)
 goto FoundSpecialChar;
   ++NextBuf;
 }
@@ -1248,24 +1248,25 @@
 }
 #endif
 
-while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
+while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0' && NextBuf 
== End)
   ++NextBuf;
 
 #ifdef __SSE2__
 FoundSpecialChar:
 #endif
 Offs += NextBuf-Buf;
 Buf = NextBuf;
 
+// If end of file, exit.
+if (Buf == End) break;
+
 if (Buf[0] == '\n' || Buf[0] == '\r') {
   // If this is \n\r or \r\n, skip both characters.
   if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
 ++Offs, ++Buf;
   ++Offs, ++Buf;
   LineOffsets.push_back(Offs);
 } else {
-  // Otherwise, this is a null.  If end of file, exit.
-  if (Buf == End) break;
   // Otherwise, skip the null.
   ++Offs, ++Buf;
 }


Index: lib/Basic/SourceManager.cpp
===
--- lib/Basic/SourceManager.cpp
+++ lib/Basic/SourceManager.cpp
@@ -1227,7 +1227,7 @@
 
 // First fix up the alignment to 16 bytes.
 while (((uintptr_t)NextBuf & 0xF) != 0) {
-  if (*NextBuf == '\n' || *NextBuf == '\r' || *NextBuf == '\0')
+  if (*NextBuf == '\n' || *NextBuf == '\r' || *NextBuf == '\0' || NextBuf == End)
 goto FoundSpecialChar;
   ++NextBuf;
 }
@@ -1248,24 +1248,25 @@
 }
 #endif
 
-while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
+while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0' && NextBuf == End)
   ++NextBuf;
 
 #ifdef __SSE2__
 FoundSpecialChar:
 #endif
 Offs += NextBuf-Buf;
 Buf = NextBuf;
 
+// If end of file, exit.
+if (Buf == End) break;
+
 if (Buf[0] == '\n' || Buf[0] == '\r') {
   // If this is \n\r or \r\n, skip both characters.
   if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
 ++Offs, ++Buf;
   ++Offs, ++Buf;
   LineOffsets.push_back(Offs);
 } else {
-  // Otherwise, this is a null.  If end of file, exit.
-  if (Buf == End) break;
   // Otherwise, skip the null.
   ++Offs, ++Buf;
 }
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-09-30 Thread Keno Fischer via cfe-commits
loladiro created this revision.
loladiro added a reviewer: doug.gregor.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.

This implements a proposal by Doug Gregor on cfe-dev a couple of years ago, to 
allow the compiler to emit strong symbols for explicit template instantiations. 
Doug's spec, which I have tried to follow can be found here: 
http://lists.llvm.org/pipermail/cfe-dev/attachments/20111203/5e1c6c35/attachment.html.
 I usually work over in LLVM-land and have only contributed the occasional bug 
fix to clang, so please let me know how this patch can be improved. I'm also 
not fully done testing it yet (only did so on the toy example I included as a 
test case), but I wanted to get this out there to get feedback. 




Repository:
  rL LLVM

http://reviews.llvm.org/D13330

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/AST/ASTContext.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp

Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,22 @@
+// RUN: %clang -cc1 -std=c++11 -fsyntax-only -verify %s
+
+template < typename T > struct foo1 { };
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{requires a previous declaration}}
+
+template < typename T > struct foo2 { };
+extern template struct foo2; // expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct foo3 { };
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct __attribute__((unique_instantiation)) foo4 { }; // expected-error{{not a explicit template declaration}}
+
+template < typename T > struct foo5 { };
+extern template struct foo5; // expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo5; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct foo6 { };
+extern template struct  __attribute__((unique_instantiation)) foo6; // expected-note{{previous explicit instantiation is here}}
+template struct foo6; // expected-error{{must be specified on all declarations}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang -std=c++11 -emit-llvm -O0 -c -S -o - %s | FileCheck %s
+
+template < typename T > struct foo {
+T x;
+T getX() { return x; }
+};
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+int footest() {
+auto var = foo{5};
+return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7321,20 +7321,25 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
 ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl && PrevDecl->hasAttr() &&
+  !Specialization->hasAttr()) {
+Diag(Specialization->getLocStart(),diag::err_unique_instantiation_not_previous);
+Diag(PrevDecl->getLocStart(),diag::note_previous_explicit_instantiation);
+  }
+
   // Add the explicit instantiation into its lexical context. However,
   // since explicit instantiations are never found by name lookup, we
   // just put it into the declaration context directly.
   Specialization->setLexicalDeclContext(CurContext);
   CurContext->addDecl(Specialization);
 
   // Syntax is now OK, so return if it has no other effect on semantics.
   if (HasNoEffect) {
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
 return Specialization;
   }
 
@@ -7388,14 +7393,7 @@
   }
 }
 
-// Set the template specialization kind. Make sure it is set before
-// instantiating the members which will trigger ASTConsumer callbacks.
-Specialization->setTemplateSpecializationKind(TSK);
 InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
-  } else {
-
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
   }
 
   return 

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-01 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Thanks for the quick review.



Comment at: include/clang/Basic/Attr.td:1462
@@ +1461,3 @@
+def UniqueInstantiation : InheritableAttr {
+  let Spellings = [GCC<"unique_instantiation">];
+  let Subjects = SubjectList<[CXXRecord]>;

aaron.ballman wrote:
> This is not a GCC attribute, so it should not be spelled as such. Since this 
> only applies to C++ code, I would recommend a C++11 spelling (in the clang 
> namespace). If you think this is something C++03 and earlier code would 
> really benefit from, then you could also add a GNU-style spelling.
No, this is C++11 only. Will change the spelling.


Comment at: include/clang/Basic/Attr.td:1464
@@ +1463,3 @@
+  let Subjects = SubjectList<[CXXRecord]>;
+  let Documentation = [Undocumented];
+}

aaron.ballman wrote:
> Please, no undocumented attributes.
Will document.


Comment at: include/clang/Basic/DiagnosticSemaKinds.td:2443
@@ -2442,1 +2442,3 @@
   ":must be between 1 and %2}2">;
+def err_unique_instantiation_wrong_decl : Error<
+  "unique_instantiation attribute on something that is not a explicit template 
declaration or instantiation.">;

aaron.ballman wrote:
> Would this make more sense as an option in warn_attribute_wrong_decl_type 
> instead? (there's an err_ version as well if you wish to keep this an error).
> 
> Also, please ensure that the attribute is quoted in the diagnostic -- it 
> makes things less confusing for the user.
Ok, so should I add an "explicit template instantiations" option to that err?


Comment at: lib/AST/ASTContext.cpp:8244
@@ -8242,2 +8243,3 @@
   case TSK_ExplicitInstantiationDefinition:
-return GVA_StrongODR;
+CTSD = dyn_cast(FD->getDeclContext());
+if (!CTSD || !CTSD->hasAttr())

aaron.ballman wrote:
> I think this would be easier to read (and not have to hoist a declaration out 
> of the switch) as:
> 
> ```
> if (const auto *CTSD = dyn_cast<>()) {
>   if (CTSD->hasAttr<>())
> return GVA_StrongExternal;
> }
> return GVA_StrongODR;
> ```
> 
Ok.


Comment at: lib/Sema/SemaDeclAttr.cpp:4539
@@ +4538,3 @@
+// by an ExplicitInstantiationDeclaration.
+if (CTSD->getSpecializationKind() == TSK_ExplicitInstantiationDefinition) {
+  if (!CTSD->getPreviousDecl())

aaron.ballman wrote:
> Why is this required as part of the feature design? It seems restrictive.
This was part of Doug's original Spec, so I implemented it:



> A unique explicit instantiation definition shall follow an explicit
> instantiation declaration of the same entity. [//Note//: this
> requirement encourages a programming style that uses unique explicit
> instantiation declarations (typically in a header) to suppress
> implicit instantiations of a template or its members, so that the
> unique explicit instantiation definition of that template or its members
> is unique. //- end note//]

I think that makes a decent amount of sense, since you really want to avoid the 
case where some translation units don't see the extern template declaration.



Comment at: lib/Sema/SemaDeclAttr.cpp:4546
@@ +4545,3 @@
+// have performed the same check on the previous declaration here.
+CXXRecordDecl *Previous = CTSD->getPreviousDecl();
+if (Previous) {

aaron.ballman wrote:
> Is this something that can be handled by mergeDeclAttribute()? I'm not 
> certain how that interplays with templates specifically, but usually we do 
> this sort of logic within a Sema::mergeFooAttr() function.
Hmm, I'm not sure, the goal of this is to ensure that all declarations and 
definitions of this extern template have the attribute set. It's not really 
`merging` per se. Though I suppose it could be made to fit in that framework.


Repository:
  rL LLVM

http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-01 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: include/clang/Basic/Attr.td:1462
@@ +1461,3 @@
+def UniqueInstantiation : InheritableAttr {
+  let Spellings = [GCC<"unique_instantiation">];
+  let Subjects = SubjectList<[CXXRecord]>;

loladiro wrote:
> aaron.ballman wrote:
> > This is not a GCC attribute, so it should not be spelled as such. Since 
> > this only applies to C++ code, I would recommend a C++11 spelling (in the 
> > clang namespace). If you think this is something C++03 and earlier code 
> > would really benefit from, then you could also add a GNU-style spelling.
> No, this is C++11 only. Will change the spelling.
It doesn't appear like the grammar allows attributes to be specified on 
explicit template definitions. I'll change the spelling to GNU:

```
error:
  an attribute list cannot appear here
template struct foo [[clang::unique_instantiation]];
 ^~~
[[clang::unique_instantiation]]
error:
  an attribute list cannot appear here
template struct [[clang::unique_instantiation]] foo;
^~~
error:
  an attribute list cannot appear here
template [[clang::unique_instantiation]] struct foo;
 ^~~
error:
  an attribute list cannot appear here
[[clang::unique_instantiation]] template struct foo;
^~~
1 error generated.
FileCheck error: '-' is empty.
```


Repository:
  rL LLVM

http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-02 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 36332.
loladiro added a comment.

Address review comments. I had to add a special case to 
checkNewAttributesAfterDef if we want to use attribute merging for explicit 
template instantiations, because the Microsoft ABI allows adding dll attributes 
to the explicit template definition, but not the declaration (which clang 
considers to be the record's definition).


Repository:
  rL LLVM

http://reviews.llvm.org/D13330

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp

Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang -cc1 -std=c++11 -fsyntax-only -verify %s
+
+template < typename T > struct foo1 { };
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{requires a previous declaration}}
+
+template < typename T > struct foo2 { };
+extern template struct foo2; // expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct foo3 { };
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct __attribute__((unique_instantiation)) foo4 { }; // expected-error{{only applies to explicit template declarations or definitions}}
+
+template < typename T > struct foo5 { };
+extern template struct  __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5; // expected-error{{must be specified on all declarations}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,15 @@
+// RUN: %clang -std=c++11 -emit-llvm -O0 -c -S -o - %s | FileCheck %s
+
+template < typename T > struct foo {
+T x;
+T getX() { return x; }
+};
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+int footest() {
+auto var = foo{5};
+return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7321,20 +7321,22 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
 ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl)
+mergeDeclAttributes(Specialization, PrevDecl);
+
   // Add the explicit instantiation into its lexical context. However,
   // since explicit instantiations are never found by name lookup, we
   // just put it into the declaration context directly.
   Specialization->setLexicalDeclContext(CurContext);
   CurContext->addDecl(Specialization);
 
   // Syntax is now OK, so return if it has no other effect on semantics.
   if (HasNoEffect) {
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
 return Specialization;
   }
 
@@ -7388,14 +7390,7 @@
   }
 }
 
-// Set the template specialization kind. Make sure it is set before
-// instantiating the members which will trigger ASTConsumer callbacks.
-Specialization->setTemplateSpecializationKind(TSK);
 InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
-  } else {
-
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
   }
 
   return Specialization;
Index: lib/Sema/SemaDeclAttr.cpp
===
--- lib/Sema/SemaDeclAttr.cpp
+++ lib/Sema/SemaDeclAttr.cpp
@@ -4529,6 +4529,29 @@
 Attr.getAttributeSpellingListIndex()));
 }
 
+
+static void handleUniqueInstantiation(Sema &S, Decl *D,
+  const AttributeList &Attr) {
+  if (auto *CTSD = dyn_cast(D)) {
+// If this is an explicit instantiation definition. Check that it was preceeded
+// by an ExplicitInstantiationDeclaration. Note, this
+// requirement encourages a programming style that uses unique explicit
+// instantiation declarations

Re: [PATCH] D12854: [SourceManager] Support buffers that are not null-terminated

2015-10-02 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Bump. Could somebody take a look at this?


Repository:
  rL LLVM

http://reviews.llvm.org/D12854



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D12854: [SourceManager] Support buffers that are not null-terminated

2015-10-02 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Hmm, you're right. And I am actually constructing it in such a way that it's 
supposed to have it, so I wonder why it ran off the rails here. Will take 
another look.


Repository:
  rL LLVM

http://reviews.llvm.org/D12854



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D12854: [SourceManager] Support buffers that are not null-terminated

2015-10-02 Thread Keno Fischer via cfe-commits
loladiro abandoned this revision.
loladiro added a comment.

Oh, I see it checks for the null terminator past the end of the given memory 
block on construction, but if the memory after changes later this just keeps 
running. Well, that's quite a trap, but I guess that's what you get for not 
understanding the API ;).


Repository:
  rL LLVM

http://reviews.llvm.org/D12854



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-03 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Thoughts on allowing this attribute to be specified on the templated class 
itself, with the intention of never allowing any implicit instantiation? As an 
example, consider SymbolTableListTraits in LLVM. It can only ever be used as an 
explicit instantiation (because the full implementation is not available).


Repository:
  rL LLVM

http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2015-10-03 Thread Keno Fischer via cfe-commits
loladiro created this revision.
loladiro added reviewers: aaron.ballman, rsmith, rnk.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.

When we were looking at a template instantiation, that itself was a template 
instantiation
(say a templated member of a templated class), we weren't looking back far 
enough along
the chain of instantiations to find a VisibilityAttr (which we don't copy when 
instantiating
templates). This patch attempts to address that as well as adding a few test 
cases for these
situations.

Repository:
  rL LLVM

http://reviews.llvm.org/D13419

Files:
  lib/AST/Decl.cpp
  lib/AST/DeclCXX.cpp
  test/CodeGenCXX/visibility.cpp

Index: test/CodeGenCXX/visibility.cpp
===
--- test/CodeGenCXX/visibility.cpp
+++ test/CodeGenCXX/visibility.cpp
@@ -1314,3 +1314,57 @@
   // CHECK-LABEL: define void @_ZN6test693foo1fEv
   // CHECK-HIDDEN-LABEL: define hidden void @_ZN6test693foo1fEv
 }
+
+namespace test70 {
+  template < typename T > class foo {
+  public:
+  T x;
+  template < typename S >
+  HIDDEN S AddS(S);
+  template < typename S > class HIDDEN barS {
+public:
+  static S AddS2(foo x, S);
+  };
+  template < typename S > class HIDDEN barZ {
+  public:
+template < typename Z >
+  static S AddSZ(foo x, S, Z);
+  };
+  };
+
+  // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+  // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+  template < typename T >
+  template < typename S >
+  HIDDEN S foo::AddS(S y) {
+  return ((S) x) + y;
+  }
+
+  // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+  // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+  template < typename T >
+  template < typename S >
+  HIDDEN S foo::barS::AddS2(foo x, S y) {
+  return ((S) x.x) + y;
+  }
+
+  // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+  // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+  template < typename T >
+  template < typename S >
+  template < typename Z >
+  HIDDEN S foo::barZ::AddSZ(foo x, S y, Z z) {
+  return ((S) x.x) + y + ((S) z);
+  }
+
+  extern template struct foo;
+  template struct foo;
+
+  void f() {
+  auto var = foo{5};
+  auto bar = var.AddS((long long)3);
+  auto bar2 = decltype(var)::barS::AddS2(var,3);
+  auto bar3 = decltype(var)::barZ::AddSZ(var,3,(char)0);
+  }
+}
+
Index: lib/AST/DeclCXX.cpp
===
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1261,20 +1261,22 @@
   if (auto *TD = dyn_cast(this)) {
 auto From = TD->getInstantiatedFrom();
 if (auto *CTD = From.dyn_cast()) {
-  while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
+  auto *NewCTD = CTD;
+  do {
+CTD = NewCTD;
 if (NewCTD->isMemberSpecialization())
   break;
-CTD = NewCTD;
-  }
+  } while ((NewCTD = CTD->getInstantiatedFromMemberTemplate()));
   return CTD->getTemplatedDecl()->getDefinition();
 }
 if (auto *CTPSD =
 From.dyn_cast()) {
-  while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
+  auto *NewCTPSD = CTPSD;
+  do {
+CTPSD = NewCTPSD;
 if (NewCTPSD->isMemberSpecialization())
   break;
-CTPSD = NewCTPSD;
-  }
+  } while ((NewCTPSD = CTPSD->getInstantiatedFromMember()));
   return CTPSD->getDefinition();
 }
   }
Index: lib/AST/Decl.cpp
===
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1049,7 +1049,9 @@
   // If this is a member class of a specialization of a class template
   // and the corresponding decl has explicit visibility, use that.
   if (const CXXRecordDecl *RD = dyn_cast(ND)) {
-CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+const CXXRecordDecl *InstantiatedFrom = RD->getTemplateInstantiationPattern();
+if (!InstantiatedFrom)
+  InstantiatedFrom = RD->getInstantiatedFromMemberClass();
 if (InstantiatedFrom)
   return getVisibilityOf(InstantiatedFrom, kind);
   }
@@ -1084,16 +1086,11 @@
   }
   // Also handle function template specializations.
   if (const FunctionDecl *fn = dyn_cast(ND)) {
-// If the function is a specialization of a template with an
-// explicit visibility attribute, use that.
-if (FunctionTemplateSpecializationInfo *templateInfo
-  = fn->getTemplateSpecializationInfo())
-  return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
- kind);
-
-// If the function is a member of a specialization of a class template
+// If the function is a member of a specialization of a some template
 // and the corr

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-03 Thread Keno Fischer via cfe-commits
loladiro removed rL LLVM as the repository for this revision.
loladiro updated this revision to Diff 36459.
loladiro added a comment.

Rebased, added support for unique_instantiation on explicit function templates 
and fix the case where one record is embedded in another and the outer is 
explicitly instantiated. Add testcases for all of these.


http://reviews.llvm.org/D13330

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp

Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang -cc1 -std=c++11 -fsyntax-only -verify %s
+
+template < typename T > struct foo1 { };
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{requires a previous declaration}}
+
+template < typename T > struct foo2 { };
+extern template struct foo2; // expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct foo3 { };
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct __attribute__((unique_instantiation)) foo4 { }; // expected-error{{only applies to explicit template declarations or definitions}}
+
+template < typename T > struct foo5 { };
+extern template struct  __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5; // expected-error{{must be specified on all declarations}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang -std=c++11 -emit-llvm -O0 -c -S -o - %s | FileCheck %s
+
+template < typename T > struct foo {
+T x;
+T getX() { return x; }
+struct bar {
+T y;
+bar(T y) : y(y) {}
+};
+};
+template < typename T > T bar();
+
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK: define void @_ZN3fooIiE3barC2Ei
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr void @_ZN3fooIiE3barC2Ei
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+extern template __attribute__((unique_instantiation)) int bar();
+
+template < typename T > T bar() {
+return (T)0;
+}
+
+// CHECK: define i32 @_Z3barIiET_v()
+// CHECK-NOT: define weak_odr i32 @_Z3barIiET_v()
+template __attribute__((unique_instantiation)) int bar();
+
+int footest() {
+auto var = foo{5};
+auto var2 = foo::bar{5};
+auto x = bar();
+return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7330,20 +7330,22 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
 ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl)
+mergeDeclAttributes(Specialization, PrevDecl);
+
   // Add the explicit instantiation into its lexical context. However,
   // since explicit instantiations are never found by name lookup, we
   // just put it into the declaration context directly.
   Specialization->setLexicalDeclContext(CurContext);
   CurContext->addDecl(Specialization);
 
   // Syntax is now OK, so return if it has no other effect on semantics.
   if (HasNoEffect) {
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
 return Specialization;
   }
 
@@ -7397,14 +7399,7 @@
   }
 }
 
-// Set the template specialization kind. Make sure it is set before
-// instantiating the members which will trigger ASTConsumer callbacks.
-Specialization->setTemplateSpecializationKind(TSK);
 InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
-  } else {
-
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
   }
 
   return Specialization;
@@ -7855,11 +7850,34 @@
   return (Decl*) nullptr;
   }
 
+  bool HadDeclaration = Specialization->getTemplateSpecializationKind() ==
+TSK_ExplicitInstantiationDeclaration;
+  bool HadUniqueInstantiation = Specialization->

[PATCH] D13421: Fix makefile build on OSX when ARM targets are not enabled

2015-10-04 Thread Keno Fischer via cfe-commits
loladiro created this revision.
loladiro added a reviewer: beanz.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.
Herald added subscribers: rengolin, aemerson.

When LLVM/Clang is built without ARM support, the ios_kext runtime library is 
not built, but without this patch, the Makefile still tries to copy it. This is 
a recent regression, because the ios_kext library used to also be built on 
x86_64.

Repository:
  rL LLVM

http://reviews.llvm.org/D13421

Files:
  runtime/compiler-rt/Makefile

Index: runtime/compiler-rt/Makefile
===
--- runtime/compiler-rt/Makefile
+++ runtime/compiler-rt/Makefile
@@ -89,8 +89,10 @@
 endif
 
 ifneq ($(IOS_SDK),)
+ifneq (,$(filter ARM AARCH64,$(TARGETS_TO_BUILD)))
 RuntimeLibrary.darwin.Configs += cc_kext_ios.a
 endif
+endif
 
 ifneq ($(IOSSIM_SDK),)
 RuntimeLibrary.darwin.Configs += asan_iossim_dynamic.dylib \


Index: runtime/compiler-rt/Makefile
===
--- runtime/compiler-rt/Makefile
+++ runtime/compiler-rt/Makefile
@@ -89,8 +89,10 @@
 endif
 
 ifneq ($(IOS_SDK),)
+ifneq (,$(filter ARM AARCH64,$(TARGETS_TO_BUILD)))
 RuntimeLibrary.darwin.Configs += cc_kext_ios.a
 endif
+endif
 
 ifneq ($(IOSSIM_SDK),)
 RuntimeLibrary.darwin.Configs += asan_iossim_dynamic.dylib \
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r249281 - Fix makefile build on OSX when ARM targets are not enabled

2015-10-04 Thread Keno Fischer via cfe-commits
Author: kfischer
Date: Sun Oct  4 13:51:04 2015
New Revision: 249281

URL: http://llvm.org/viewvc/llvm-project?rev=249281&view=rev
Log:
Fix makefile build on OSX when ARM targets are not enabled

Summary: When LLVM/Clang is built without ARM support, the ios_kext runtime
library is not built, but without this patch, the Makefile still tries to
copy it. This is a recent regression, because the ios_kext library used
to also be built on x86_64.

Reviewers: beanz

Subscribers: aemerson, cfe-commits, rengolin

Differential Revision: http://reviews.llvm.org/D13421

Modified:
cfe/trunk/runtime/compiler-rt/Makefile

Modified: cfe/trunk/runtime/compiler-rt/Makefile
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/runtime/compiler-rt/Makefile?rev=249281&r1=249280&r2=249281&view=diff
==
--- cfe/trunk/runtime/compiler-rt/Makefile (original)
+++ cfe/trunk/runtime/compiler-rt/Makefile Sun Oct  4 13:51:04 2015
@@ -89,8 +89,10 @@ RuntimeLibrary.darwin.Configs += ios.a p
 endif
 
 ifneq ($(IOS_SDK),)
+ifneq (,$(filter ARM AARCH64,$(TARGETS_TO_BUILD)))
 RuntimeLibrary.darwin.Configs += cc_kext_ios.a
 endif
+endif
 
 ifneq ($(IOSSIM_SDK),)
 RuntimeLibrary.darwin.Configs += asan_iossim_dynamic.dylib \


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-04 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 36476.
loladiro added a comment.

Also set the correct linkage on vtables of classes with the new attribute.


http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp

Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang -cc1 -std=c++11 -fsyntax-only -verify %s
+
+template < typename T > struct foo1 { };
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{requires a previous declaration}}
+
+template < typename T > struct foo2 { };
+extern template struct foo2; // expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct foo3 { };
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3; // expected-error{{must be specified on all declarations}}
+
+template < typename T > struct __attribute__((unique_instantiation)) foo4 { }; // expected-error{{only applies to explicit template declarations or definitions}}
+
+template < typename T > struct foo5 { };
+extern template struct  __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5; // expected-error{{must be specified on all declarations}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang -std=c++11 -emit-llvm -O0 -c -S -o - %s | FileCheck %s
+
+template < typename T > struct foo {
+T x;
+T getX() { return x; }
+struct bar {
+T y;
+bar(T y) : y(y) {}
+};
+};
+template < typename T > T bar();
+
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK: define void @_ZN3fooIiE3barC2Ei
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr void @_ZN3fooIiE3barC2Ei
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+extern template __attribute__((unique_instantiation)) int bar();
+
+template < typename T > T bar() {
+return (T)0;
+}
+
+// CHECK: define i32 @_Z3barIiET_v()
+// CHECK-NOT: define weak_odr i32 @_Z3barIiET_v()
+template __attribute__((unique_instantiation)) int bar();
+
+int footest() {
+auto var = foo{5};
+auto var2 = foo::bar{5};
+auto x = bar();
+return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7330,20 +7330,22 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
 ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl)
+mergeDeclAttributes(Specialization, PrevDecl);
+
   // Add the explicit instantiation into its lexical context. However,
   // since explicit instantiations are never found by name lookup, we
   // just put it into the declaration context directly.
   Specialization->setLexicalDeclContext(CurContext);
   CurContext->addDecl(Specialization);
 
   // Syntax is now OK, so return if it has no other effect on semantics.
   if (HasNoEffect) {
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
 return Specialization;
   }
 
@@ -7397,14 +7399,7 @@
   }
 }
 
-// Set the template specialization kind. Make sure it is set before
-// instantiating the members which will trigger ASTConsumer callbacks.
-Specialization->setTemplateSpecializationKind(TSK);
 InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
-  } else {
-
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
   }
 
   return Specialization;
@@ -7855,11 +7850,34 @@
   return (Decl*) nullptr;
   }
 
+  bool HadDeclaration = Specialization->getTemplateSpecializationKind() ==
+TSK_ExplicitInstantiationDeclaration;
+  bool HadUniqueInstantiation = Specialization->hasAttr();
+  SourceLocation OldUniqueInstantiationLoc;
+  if (HadUniqueInstantiation) {
+OldUniqueInstantiationLoc =
+  Specializ

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-04 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Ok, I have tested this more extensively now. I'm happy with the results. Here's 
a patch that applies this to LLVM for example: 
https://gist.github.com/Keno/79b08a4b187c4d950dd0

Before:

  $llvm-objdump -weak-bind libLLVM-3.8svn.dylib | wc -l
   300

After:

  $llvm-objdump -weak-bind libLLVM-3.8svn.dylib | wc -l
   15

with none of those being LLVM symbols.


http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2015-10-05 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 36565.
loladiro added a comment.

Address review comment re loop structure. Reword comment that had a typo to 
both fix the typo and make the intent of the code more clear.


Repository:
  rL LLVM

http://reviews.llvm.org/D13419

Files:
  lib/AST/Decl.cpp
  lib/AST/DeclCXX.cpp
  test/CodeGenCXX/visibility.cpp

Index: test/CodeGenCXX/visibility.cpp
===
--- test/CodeGenCXX/visibility.cpp
+++ test/CodeGenCXX/visibility.cpp
@@ -1314,3 +1314,57 @@
   // CHECK-LABEL: define void @_ZN6test693foo1fEv
   // CHECK-HIDDEN-LABEL: define hidden void @_ZN6test693foo1fEv
 }
+
+namespace test70 {
+  template < typename T > class foo {
+  public:
+  T x;
+  template < typename S >
+  HIDDEN S AddS(S);
+  template < typename S > class HIDDEN barS {
+public:
+  static S AddS2(foo x, S);
+  };
+  template < typename S > class HIDDEN barZ {
+  public:
+template < typename Z >
+  static S AddSZ(foo x, S, Z);
+  };
+  };
+
+  // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+  // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4AddSIxEET_S3_
+  template < typename T >
+  template < typename S >
+  HIDDEN S foo::AddS(S y) {
+  return ((S) x) + y;
+  }
+
+  // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+  // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barSIxE5AddS2ES1_x
+  template < typename T >
+  template < typename S >
+  HIDDEN S foo::barS::AddS2(foo x, S y) {
+  return ((S) x.x) + y;
+  }
+
+  // CHECK: define linkonce_odr hidden i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+  // CHECK-NOT: define linkonce_odr i64 @_ZN6test703fooIiE4barZIxE5AddSZIcEExS1_xT_
+  template < typename T >
+  template < typename S >
+  template < typename Z >
+  HIDDEN S foo::barZ::AddSZ(foo x, S y, Z z) {
+  return ((S) x.x) + y + ((S) z);
+  }
+
+  extern template struct foo;
+  template struct foo;
+
+  void f() {
+  auto var = foo{5};
+  auto bar = var.AddS((long long)3);
+  auto bar2 = decltype(var)::barS::AddS2(var,3);
+  auto bar3 = decltype(var)::barZ::AddSZ(var,3,(char)0);
+  }
+}
+
Index: lib/AST/DeclCXX.cpp
===
--- lib/AST/DeclCXX.cpp
+++ lib/AST/DeclCXX.cpp
@@ -1261,17 +1261,19 @@
   if (auto *TD = dyn_cast(this)) {
 auto From = TD->getInstantiatedFrom();
 if (auto *CTD = From.dyn_cast()) {
-  while (auto *NewCTD = CTD->getInstantiatedFromMemberTemplate()) {
-if (NewCTD->isMemberSpecialization())
+  while (!CTD->isMemberSpecialization()) {
+auto *NewCTD = CTD->getInstantiatedFromMemberTemplate();
+if (!NewCTD)
   break;
 CTD = NewCTD;
   }
   return CTD->getTemplatedDecl()->getDefinition();
 }
 if (auto *CTPSD =
 From.dyn_cast()) {
-  while (auto *NewCTPSD = CTPSD->getInstantiatedFromMember()) {
-if (NewCTPSD->isMemberSpecialization())
+  while (!CTPSD->isMemberSpecialization()) {
+auto *NewCTPSD = CTPSD->getInstantiatedFromMember();
+if (!NewCTPSD)
   break;
 CTPSD = NewCTPSD;
   }
Index: lib/AST/Decl.cpp
===
--- lib/AST/Decl.cpp
+++ lib/AST/Decl.cpp
@@ -1049,7 +1049,9 @@
   // If this is a member class of a specialization of a class template
   // and the corresponding decl has explicit visibility, use that.
   if (const CXXRecordDecl *RD = dyn_cast(ND)) {
-CXXRecordDecl *InstantiatedFrom = RD->getInstantiatedFromMemberClass();
+const CXXRecordDecl *InstantiatedFrom = RD->getTemplateInstantiationPattern();
+if (!InstantiatedFrom)
+  InstantiatedFrom = RD->getInstantiatedFromMemberClass();
 if (InstantiatedFrom)
   return getVisibilityOf(InstantiatedFrom, kind);
   }
@@ -1084,16 +1086,12 @@
   }
   // Also handle function template specializations.
   if (const FunctionDecl *fn = dyn_cast(ND)) {
-// If the function is a specialization of a template with an
-// explicit visibility attribute, use that.
-if (FunctionTemplateSpecializationInfo *templateInfo
-  = fn->getTemplateSpecializationInfo())
-  return getVisibilityOf(templateInfo->getTemplate()->getTemplatedDecl(),
- kind);
-
-// If the function is a member of a specialization of a class template
-// and the corresponding decl has explicit visibility, use that.
-FunctionDecl *InstantiatedFrom = fn->getInstantiatedFromMemberFunction();
+// If the function is a template specialization or a member of
+// a specialized class template and the corresponding decl has
+// explicit visibility, use that.
+FunctionDecl *InstantiatedFrom = fn->getTemplateInstantiationPattern();
+if (!InstantiatedFrom)
+  InstantiatedFrom = fn->getInstantiatedFromMemberFunction();

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-15 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: include/clang/Basic/AttrDocs.td:1638
@@ +1637,3 @@
+
+Note that to ensure correct execution the user MUST make certain that no
+other translation unit has an implicit instantiation of the same entity. In

aaron.ballman wrote:
> In the unlikely event the user gets this wrong (lol), is there a way to 
> diagnose this on the backend? The wording here makes it sound like it's 
> possible for this to cause silent miscompiles, which would be unfortunate.
I don't think there is anything that can be really done here. I believe the 
static linker will link this just fine (there'll be one weak and one strong 
symbol). The difficulty of course arises with dynamic linkers that won't bother 
looking for any weak symbols to merge with (at least the OS X one doesn't). I 
suppose it's not really that different from missing a `weak` attribute on some 
declarations but not others.


Comment at: lib/CodeGen/CGVTables.cpp:744
@@ +743,3 @@
+// UniqueInstantiationAttr), the VTable should too.
+keyFunction->dump();
+if (Context.containedInUniqueInstantiation(keyFunction))

aaron.ballman wrote:
> Looks like some debugging code accidentally made it in.
Thanks!


Comment at: lib/Sema/SemaDecl.cpp:2285
@@ +2284,3 @@
+  // here.
+  if (auto *CTSD = dyn_cast(New)) {
+TemplateSpecializationKind kind = CTSD->getSpecializationKind();

aaron.ballman wrote:
> Isn't this a bit broad? I do agree that we don't want to give incorrect 
> warnings, but it seems like this may inadvertently silence correct warnings 
> as well. If my gut feeling is wrong (which it might be), it would be good to 
> have some test cases confirming that this doesn't silence correct 
> diagnostics. 
As far as I know, this is only called from mergeDeclAttributes, which didn't 
use to be called on these before this patch. I also don't think any attributes 
but dllexport or unique_instantiation apply to these declarations and those two 
both need special processing.


http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-15 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 37555.
loladiro added a comment.

Address review comments and clang-format.


http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2339,6 +2339,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang -cc1 -std=c++11 -fsyntax-only -verify %s
+
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{requires a previous declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{must be specified on all declarations}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{must be specified on all declarations}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{must be specified on all declarations}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang -std=c++11 -emit-llvm -O0 -c -S -o - %s | FileCheck %s
+
+template 
+struct foo {
+  T x;
+  T getX() { return x; }
+  struct bar {
+T y;
+bar(T y) : y(y) {}
+  };
+};
+template 
+T bar();
+
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK: define void @_ZN3fooIiE3barC2Ei
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr void @_ZN3fooIiE3barC2Ei
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+extern template __attribute__((unique_instantiation)) int bar();
+
+template 
+T bar() {
+  return (T)0;
+}
+
+// CHECK: define i32 @_Z3barIiET_v()
+// CHECK-NOT: define weak_odr i32 @_Z3barIiET_v()
+template __attribute__((unique_instantiation)) int bar();
+
+int footest() {
+  auto var = foo{5};
+  auto var2 = foo::bar{5};
+  auto x = bar();
+  return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7330,20 +7330,22 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
 ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl)
+mergeDeclAttributes(Specialization, PrevDecl);
+
   // Add the explicit instantiation into its lexical context. However,
   // since explicit instantiations are never found by name lookup, we
   // just put it into the declaration context directly.
   Specialization->setLexicalDeclContext(CurContext);
   CurContext->addDecl(Specialization);
 
   // Syntax is now OK, so return if it has no other effect on semantics.
   if (HasNoEffect) {
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
 return Specialization;
   }
 
@@ -7397,14 +7399,7 @@
   }
 }
 
-// Set the template specialization kind. Make sure it is set before
-// instantiating the members which will trigger ASTConsumer callbacks.
-Specialization->setTemplateSpecializationKind(TSK);
 InstantiateClassTemplateSpe

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-21 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: include/clang/Basic/Attr.td:1463
@@ +1462,3 @@
+  let Spellings = [GNU<"unique_instantiation">];
+  let Subjects = SubjectList<[Function, CXXRecord], ErrorDiag>;
+  let Documentation = [UniqueInstantiationDocs];

majnemer wrote:
> What about variable templates?
I hadn't tried before, but looking at this, I'd say they're broken in clang 
anyway and I'm gonna say fixing that is outside the scope of this revision:
```
$ cat test.cpp
template  T n;
extern template int n;
template int n;

int main() {
return n;
}
$ ./usr/bin/clang++ -std=c++14 -c test.cpp
$ nm test.o
 T main
U _Z1nIiE
$ nm test.o.gcc6
[snip]
060098c u _Z1nIiE
```


Comment at: include/clang/Basic/DiagnosticSemaKinds.td:2456
@@ -2450,1 +2455,3 @@
+def err_unique_instantiation_not_previous : Error<
+  "The unique_instantiation must be specified on all declarations and 
definitions of a particular explicit template instantiation.">;
 

aaron.ballman wrote:
> Should say: the 'unique_instantiation' attribute.
> 
> Also, I'm not keen on "a particular" as it's very non-specific.
> 
> I wonder if we need err_unique_instantiation_no_declaration and 
> err_unique_instantiation_not_previous to be separate diagnostics? Aren't they 
> both effectively saying, 
> 
> "a 'unique_instantiation' attribute must be specified for all declarations 
> and definitions of the explicit template instantiation"
They are checking for two different conditions in the spec. One requires that 
all explicit template instantiations with this attribute have a declaration, 
the other that every declaration/definition has the attribute.


Comment at: test/CodeGenCXX/unique-instantiation.cpp:1
@@ +1,2 @@
+// RUN: %clang -std=c++11 -emit-llvm -O0 -c -S -o - %s | FileCheck %s
+

majnemer wrote:
> Is -O0 needed here?
No, removing.


http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-21 Thread Keno Fischer via cfe-commits
loladiro set the repository for this revision to rL LLVM.
loladiro updated this revision to Diff 38039.
loladiro added a comment.

Address review comments.


Repository:
  rL LLVM

http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2339,6 +2339,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang -cc1 -std=c++11 -fsyntax-only -verify %s
+
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{requires a previous declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{must be specified for all declarations}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{must be specified for all declarations}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{must be specified for all declarations}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang -std=c++11 -emit-llvm -c -S -o - %s | FileCheck %s
+
+template 
+struct foo {
+  T x;
+  T getX() { return x; }
+  struct bar {
+T y;
+bar(T y) : y(y) {}
+  };
+};
+template 
+T bar();
+
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK: define void @_ZN3fooIiE3barC2Ei
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr void @_ZN3fooIiE3barC2Ei
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+extern template __attribute__((unique_instantiation)) int bar();
+
+template 
+T bar() {
+  return (T)0;
+}
+
+// CHECK: define i32 @_Z3barIiET_v()
+// CHECK-NOT: define weak_odr i32 @_Z3barIiET_v()
+template __attribute__((unique_instantiation)) int bar();
+
+int footest() {
+  auto var = foo{5};
+  auto var2 = foo::bar{5};
+  auto x = bar();
+  return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7330,20 +7330,22 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
 ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl)
+mergeDeclAttributes(Specialization, PrevDecl);
+
   // Add the explicit instantiation into its lexical context. However,
   // since explicit instantiations are never found by name lookup, we
   // just put it into the declaration context directly.
   Specialization->setLexicalDeclContext(CurContext);
   CurContext->addDecl(Specialization);
 
   // Syntax is now OK, so return if it has no other effect on semantics.
   if (HasNoEffect) {
-// Set the template specialization kind.
-Specialization->setTemplateSpecializationKind(TSK);
 return Specialization;
   }
 
@@ -7397,14 +7399,7 @@
   }
 }
 
-// Set the template specialization kind. Make sure it is set before
-// instantiating the members which will trigger ASTConsumer callbacks.
-Specialization->setTe

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-10-21 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: include/clang/Basic/Attr.td:1463
@@ +1462,3 @@
+  let Spellings = [GNU<"unique_instantiation">];
+  let Subjects = SubjectList<[Function, CXXRecord], ErrorDiag>;
+  let Documentation = [UniqueInstantiationDocs];

majnemer wrote:
> They work ok, clang just thinks that it's a declaration of a variable 
> template.  Try this:
>   template  T n = T();
>   extern template int n;
>   template int n;
I see. I'll look into adding support for it. Can you explain why my example 
doesn't work? GCC seems to allow this.


Repository:
  rL LLVM

http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D13959: Fix crash in EmitDeclMetadata mode

2015-10-21 Thread Keno Fischer via cfe-commits
loladiro created this revision.
loladiro added reviewers: rjmccall, labath.
loladiro added a subscriber: cfe-commits.
loladiro set the repository for this revision to rL LLVM.

This fixes a bug that's easily encountered in LLDB 
(https://llvm.org/bugs/show_bug.cgi?id=22875). The problem here is that we 
mangle a name during debug info emission, but never actually emit the actual 
Decl, so we run into problems here. I am not entirely sure this is the right 
fix. The comment says something about StaticLocalDeclMap, which may be better 
here, but I checked and that already existed when this functionality was added, 
which makes me think that there is some reason it wasn't used.

Repository:
  rL LLVM

http://reviews.llvm.org/D13959

Files:
  lib/CodeGen/CodeGenModule.cpp

Index: lib/CodeGen/CodeGenModule.cpp
===
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -3710,7 +3710,10 @@
   // StaticLocalDeclMap
   for (auto &I : MangledDeclNames) {
 llvm::GlobalValue *Addr = getModule().getNamedValue(I.second);
-EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
+// Some mangled names don't necessarily have an associated GlobalValue
+// in this module, e.g. if we mangled it for DebugInfo.
+if (Addr)
+  EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
   }
 }
 


Index: lib/CodeGen/CodeGenModule.cpp
===
--- lib/CodeGen/CodeGenModule.cpp
+++ lib/CodeGen/CodeGenModule.cpp
@@ -3710,7 +3710,10 @@
   // StaticLocalDeclMap
   for (auto &I : MangledDeclNames) {
 llvm::GlobalValue *Addr = getModule().getNamedValue(I.second);
-EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
+// Some mangled names don't necessarily have an associated GlobalValue
+// in this module, e.g. if we mangled it for DebugInfo.
+if (Addr)
+  EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
   }
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13959: Fix crash in EmitDeclMetadata mode

2015-10-22 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Can you provide insight as to why this is looking at MangledDeclNames rather 
than the StaticLocalDeclMap? I'd like to extend the comment with an explanation.


Repository:
  rL LLVM

http://reviews.llvm.org/D13959



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r252229 - Fix crash in EmitDeclMetadata mode

2015-11-05 Thread Keno Fischer via cfe-commits
Author: kfischer
Date: Thu Nov  5 17:18:44 2015
New Revision: 252229

URL: http://llvm.org/viewvc/llvm-project?rev=252229&view=rev
Log:
Fix crash in EmitDeclMetadata mode

Summary: This fixes a bug that's easily encountered in LLDB
(https://llvm.org/bugs/show_bug.cgi?id=22875). The problem here is that we
mangle a name during debug info emission, but never actually emit the actual
Decl, so we run into problems in EmitDeclMetadata (which assumes such a Decl
exists). Fix that by just skipping metadata emissions for mangled names that
don't have associated Decls.

Reviewers: rjmccall

Subscribers: labath, cfe-commits

Differential Revision: http://reviews.llvm.org/D13959

Modified:
cfe/trunk/lib/CodeGen/CodeGenModule.cpp

Modified: cfe/trunk/lib/CodeGen/CodeGenModule.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenModule.cpp?rev=252229&r1=252228&r2=252229&view=diff
==
--- cfe/trunk/lib/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenModule.cpp Thu Nov  5 17:18:44 2015
@@ -3707,10 +3707,12 @@ bool CodeGenModule::lookupRepresentative
 void CodeGenModule::EmitDeclMetadata() {
   llvm::NamedMDNode *GlobalMetadata = nullptr;
 
-  // StaticLocalDeclMap
   for (auto &I : MangledDeclNames) {
 llvm::GlobalValue *Addr = getModule().getNamedValue(I.second);
-EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
+// Some mangled names don't necessarily have an associated GlobalValue
+// in this module, e.g. if we mangled it for DebugInfo.
+if (Addr)
+  EmitGlobalDeclMetadata(*this, GlobalMetadata, I.first, Addr);
   }
 }
 


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-11-06 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: include/clang/Basic/Attr.td:1463
@@ +1462,3 @@
+  let Spellings = [GNU<"unique_instantiation">];
+  let Subjects = SubjectList<[Function, CXXRecord], ErrorDiag>;
+  let Documentation = [UniqueInstantiationDocs];

loladiro wrote:
> majnemer wrote:
> > They work ok, clang just thinks that it's a declaration of a variable 
> > template.  Try this:
> >   template  T n = T();
> >   extern template int n;
> >   template int n;
> I see. I'll look into adding support for it. Can you explain why my example 
> doesn't work? GCC seems to allow this.
Bump on the question of differences to GCC here.


Comment at: include/clang/Basic/DiagnosticSemaKinds.td:2456
@@ -2450,1 +2455,3 @@
+def err_unique_instantiation_not_previous : Error<
+  "'unique_instantiation' attribute must be specified for all declarations and 
definitions of this explicit template instantiation">;
 

aaron.ballman wrote:
> > They are checking for two different conditions in the spec. One requires 
> > that all explicit template instantiations with this attribute have a 
> > declaration, the other that every declaration/definition has the attribute.
> 
> Okay, I see now what this diagnostic is attempting to convey. I think it 
> should read:
> ```
> def err_unique_instantiation_no_declaration : Error<
>   "'unique_instantiation' attribute on an explicit instantiation requires a 
> previous explicit instantiation declaration">;
> ```
Sounds good.


Comment at: test/SemaCXX/unique-instantiations.cpp:23
@@ +22,2 @@
+extern template struct __attribute__((unique_instantiation)) foo5; // 
expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // 
expected-error{{must be specified for all declarations}}

aaron.ballman wrote:
> Missing tests for correct usage of the attribute. Missing tests of the 
> attribute diagnosing when given arguments.
Isn't the correct usage checked for in the CodeGen tests above?


Repository:
  rL LLVM

http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-11-06 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 39627.
loladiro updated the summary for this revision.
loladiro added a comment.

Address review feedback regarding diagnostic wording/expand tests to full text 
of diagnostic.


http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2371,6 +2371,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,28 @@
+// RUN: %clang -cc1 -std=c++11 -fsyntax-only -verify %s
+
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct  __attribute__((unique_instantiation(16))) foo6;// expected-error{{'unique_instantiation' attribute takes no arguments}}
+template struct __attribute__((unique_instantiation("Hello World"))) foo6; // expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang -std=c++11 -emit-llvm -c -S -o - %s | FileCheck %s
+
+template 
+struct foo {
+  T x;
+  T getX() { return x; }
+  struct bar {
+T y;
+bar(T y) : y(y) {}
+  };
+};
+template 
+T bar();
+
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK: define void @_ZN3fooIiE3barC2Ei
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr void @_ZN3fooIiE3barC2Ei
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+extern template __attribute__((unique_instantiation)) int bar();
+
+template 
+T bar() {
+  return (T)0;
+}
+
+// CHECK: define i32 @_Z3barIiET_v()
+// CHECK-NOT: define weak_odr i32 @_Z3barIiET_v()
+template __attribute__((unique_instantiation)) int bar();
+
+int footest() {
+  auto var = foo{5};
+  auto var2 = foo::bar{5};
+  auto x = bar();
+  return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7330,20 +7330,22 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
 ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl)
+mergeDeclAttributes(Specialization, PrevDecl)

Re: [PATCH] D13610: [CodeGen] Fix CodeGenModule::CreateGlobalInitOrDestructFunction

2016-04-12 Thread Keno Fischer via cfe-commits
loladiro added a subscriber: loladiro.
loladiro added a comment.

Thanks for this. I was about to create the same patch (after seeing this broken 
on 3.7) only to see it had already been done!


Repository:
  rL LLVM

http://reviews.llvm.org/D13610



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2016-01-06 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Bumping this again.


http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


r253190 - [CGDebugInfo] Set the size and align for reference types

2015-11-16 Thread Keno Fischer via cfe-commits
Author: kfischer
Date: Mon Nov 16 03:04:13 2015
New Revision: 253190

URL: http://llvm.org/viewvc/llvm-project?rev=253190&view=rev
Log:
[CGDebugInfo] Set the size and align for reference types

In r253186, I changed the DIBuilder API to now take size and align
for reference types as well. This was done in preparation for upcoming
changes to the Verifier that will validate that sizes match between
DI types and IR values that are declared as having those types.
This updates clang to actually pass the information through.

Modified:
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/test/CodeGenCXX/debug-info-rvalue-ref.cpp

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=253190&r1=253189&r2=253190&view=diff
==
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Mon Nov 16 03:04:13 2015
@@ -712,10 +712,6 @@ llvm::DIType *CGDebugInfo::CreatePointer
  const Type *Ty,
  QualType PointeeTy,
  llvm::DIFile *Unit) {
-  if (Tag == llvm::dwarf::DW_TAG_reference_type ||
-  Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
-return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit));
-
   // Bit size, align and offset of the type.
   // Size is always the size of a pointer. We can't use getTypeSize here
   // because that does not return the correct value for references.
@@ -723,8 +719,13 @@ llvm::DIType *CGDebugInfo::CreatePointer
   uint64_t Size = CGM.getTarget().getPointerWidth(AS);
   uint64_t Align = CGM.getContext().getTypeAlign(Ty);
 
-  return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
-Align);
+  if (Tag == llvm::dwarf::DW_TAG_reference_type ||
+  Tag == llvm::dwarf::DW_TAG_rvalue_reference_type)
+return DBuilder.createReferenceType(Tag, getOrCreateType(PointeeTy, Unit),
+Size, Align);
+  else
+return DBuilder.createPointerType(getOrCreateType(PointeeTy, Unit), Size,
+  Align);
 }
 
 llvm::DIType *CGDebugInfo::getOrCreateStructPtrType(StringRef Name,

Modified: cfe/trunk/test/CodeGenCXX/debug-info-rvalue-ref.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-rvalue-ref.cpp?rev=253190&r1=253189&r2=253190&view=diff
==
--- cfe/trunk/test/CodeGenCXX/debug-info-rvalue-ref.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/debug-info-rvalue-ref.cpp Mon Nov 16 03:04:13 2015
@@ -8,5 +8,5 @@ void foo (int &&i)
   printf("%d\n", i);
 }
 
-// CHECK: !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: 
![[INT:[0-9]+]])
+// CHECK: !DIDerivedType(tag: DW_TAG_rvalue_reference_type, baseType: 
![[INT:[0-9]+]], size: 64, align: 64)
 // CHECK: ![[INT]] = !DIBasicType(name: "int"


___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-11-26 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 41261.
loladiro added a comment.

Rebased and made the small suggested changes to the test cases.


http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2371,6 +2371,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang -cc1 -std=c++11 -fsyntax-only -verify %s
+
+// Correct usage
+template 
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+// Various examples of incorrect usage
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct  __attribute__((unique_instantiation(16))) foo6;// expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,38 @@
+// RUN: %clang -std=c++11 -emit-llvm -c -S -o - %s | FileCheck %s
+
+template 
+struct foo {
+  T x;
+  T getX() { return x; }
+  struct bar {
+T y;
+bar(T y) : y(y) {}
+  };
+};
+template 
+T bar();
+
+// CHECK: define i32 @_ZN3fooIiE4getXEv
+// CHECK: define void @_ZN3fooIiE3barC2Ei
+// CHECK-NOT: define weak_odr i32 @_ZN3fooIiE4getXEv
+// CHECK-NOT: define weak_odr void @_ZN3fooIiE3barC2Ei
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+extern template __attribute__((unique_instantiation)) int bar();
+
+template 
+T bar() {
+  return (T)0;
+}
+
+// CHECK: define i32 @_Z3barIiET_v()
+// CHECK-NOT: define weak_odr i32 @_Z3barIiET_v()
+template __attribute__((unique_instantiation)) int bar();
+
+int footest() {
+  auto var = foo{5};
+  auto var2 = foo::bar{5};
+  auto x = bar();
+  return var.getX();
+}
Index: lib/Sema/SemaTemplate.cpp
===
--- lib/Sema/SemaTemplate.cpp
+++ lib/Sema/SemaTemplate.cpp
@@ -7398,20 +7398,22 @@
   Specialization->setExternLoc(ExternLoc);
   Specialization->setTemplateKeywordLoc(TemplateLoc);
   Specialization->setRBraceLoc(SourceLocation());
+  Specialization->setTemplateSpecializationKind(TSK);
 
   if (Attr)
 ProcessDeclAttributeList(S, Specialization, Attr);
 
+  if (PrevDecl)
+mergeDeclAttributes(Specialization, PrevDecl);
+
   // Add 

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-11-26 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 41265.
loladiro added a comment.

Add support for variable templates


http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2371,6 +2371,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang -cc1 -std=c++14 -fsyntax-only -verify %s
+
+// Correct usage
+template 
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+// Usages on non-templates
+float __attribute__((unique_instantiation)) notpi(2.71828182845904523536028747135); // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+struct __attribute__((unique_instantiation)) bar {};// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+void __attribute__((unique_instantiation)) func() {}// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+// Usages that violate one of the conditions required conditions
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+T pi1 = T(3.1415926535897932385);
+template __attribute__((unique_instantiation)) float pi1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct __attribute__((unique_instantiation(16))) foo6; // expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang -std=c++14 -emit-llvm -c -S -o - %s | FileCheck %s
+
+// CHECK: @_Z2piIfE = global float
+// CHECK-NOT: @_Z2piIfE = weak_odr global float
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+template 
+struct foo {
+  T x;
+  T getX() { return x; }
+  struct bar {
+T y;

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-12-04 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Bump, is there anything else that's needed here?


http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2015-12-05 Thread Keno Fischer via cfe-commits
loladiro added a comment.

Bumping this again.


Repository:
  rL LLVM

http://reviews.llvm.org/D13419



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-12-07 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: include/clang/Basic/AttrDocs.td:1736-1755
@@ -1722,2 +1735,22 @@
+
+// Explicit template definition (in exactly ONE .cpp file)
+template struct __attribute__((unique_instantiation)) my_template;
+
+
+When the unique_instantiation attribute is specified on an explicit template
+instantiation, the compiler is given license to emit strong symbols for
+this specific explicit template instantiation.
+
+If the attribute is present on one such definition or declaration for a given
+entity, it must be present on all.
+
+Note that to ensure correct execution the user MUST make certain that no
+other translation unit has an implicit instantiation of the same entity. In
+particular this means that any usage of the entity has to be preceeded by an
+appropriate explicit template declaration or definition.
 
+It is thus recommended that explicit template declarations are placed in 
headers
+to suppress any potential implicit instantiation of the entity. In order to
+encourage this programming style, any explicit template definition with this
+attribute MUST be preceeded by an appropriate declaration.
   }];

majnemer wrote:
> Instead of using all-caps for emphasis in "ONE" and "MUST", why not bold the 
> text instead?  It would catch the eye a little faster.
Sure! I assume, this follows standard RST conventions where ** is bold?


Comment at: include/clang/Basic/DiagnosticSemaKinds.td:2533-2534
@@ -2531,1 +2532,4 @@
   ":must be between 1 and %2}2">;
+def err_unique_instantiation_wrong_decl : Error<
+  "'unique_instantiation' attribute only applies to an explicit template 
declaration or instantiation">;
+def err_unique_instantiation_no_declaration : Error<

majnemer wrote:
> I can't seem to see any users of `err_unique_instantiation_wrong_decl`.
Yes, it was replaced by adding a case to err_attribute_wrong_decl_type above. 
Will remove.


Comment at: lib/AST/ASTContext.cpp:8283-8286
@@ +8282,6 @@
+Context.containedInUniqueInstantiation(FD)) {
+  // We return GVA_StrongExternal here, instead of going through the logic
+  // below, because even if the definition is available inline, since the
+  // source specified  an explicit template instantiation, we want to make
+  // the symbol available.
+  return GVA_StrongExternal;

majnemer wrote:
> There are a lot of commas here, making it a little hard to read the 
> justification.
> 
> Perhaps something along the lines of:
> 
> > This translation unit is responsible for emitting a unique instantiation of 
> > this function regardless of whether or not the function is marked inline.
Sounds good.


Comment at: lib/CodeGen/CGVTables.cpp:744-747
@@ -743,2 +743,6 @@
   case TSK_ExplicitInstantiationDefinition:
+// If the key function has strong linkage (say due to
+// UniqueInstantiationAttr), the VTable should too.
+if (Context.containedInUniqueInstantiation(keyFunction))
+  return llvm::GlobalVariable::ExternalLinkage;
 return !Context.getLangOpts().AppleKext ?

majnemer wrote:
> What if the key function is not contained within a record which is marked as 
> `UniqueInstantiationAttr` but the key function itself is marked 
> `UniqueInstantiationAttr`?
I don't know, I'd be inclined to say the unique instantiation does not apply to 
the vtable unless it's explicit on the class, but I'd be open to differing 
opinions.


http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-12-07 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 42100.
loladiro added a comment.

Address stylistic concerns brought up by David


http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2373,6 +2373,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang -cc1 -std=c++14 -fsyntax-only -verify %s
+
+// Correct usage
+template 
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+template  T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+// Usages on non-templates
+float __attribute__((unique_instantiation)) notpi(2.71828182845904523536028747135); // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+struct __attribute__((unique_instantiation)) bar{}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+void __attribute__((unique_instantiation)) func() {} // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+// Usages that violate one of the conditions required conditions
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template  T pi1 = T(3.1415926535897932385);
+template __attribute__((unique_instantiation)) float pi1;  // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct  __attribute__((unique_instantiation(16))) foo6;// expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,44 @@
+// RUN: %clang -std=c++14 -emit-llvm -c -S -o - %s | FileCheck %s
+
+// CHECK: @_Z2piIfE = global float
+// CHECK-NOT: @_Z2piIfE = weak_odr global float
+template  T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+template 
+struct foo {
+  T x;
+  T getX() { return x; }
+  struct bar {
+T y;
+bar(T y) : y(y) {}
+  };
+};
+template 
+T b

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-12-07 Thread Keno Fischer via cfe-commits
loladiro added inline comments.


Comment at: lib/AST/ASTContext.cpp:8257-8266
@@ -8256,1 +8256,12 @@
 
+bool ASTContext::containedInUniqueInstantiation(const Decl *D) {
+  const RecordDecl *RD;
+  while ((RD = dyn_cast(D->getDeclContext( {
+auto *CTSD = dyn_cast(RD);
+if (CTSD && CTSD->hasAttr())
+  return true;
+D = RD;
+  }
+  return false;
+}
+

majnemer wrote:
> Function templates can contain class templates which contain functions.  I 
> think this code will return false if the outermost function template is the 
> only one annotated with UniqueInstantiationAttr.
So you're concerned about this case:
```
template < typename T > auto foo( T x ) {
  class inner {
  T y;
  public:
  virtual ~inner() {}
  inner(T y) : y(y) {}
  T getY() { return y; }
  };
  return inner{x}.getY();
}

extern template __attribute__((unique_instantiation)) auto foo(int);
template __attribute__((unique_instantiation)) auto foo(int);
```
Right now the inner class's vtable and method is linkonce_odr. If you think it 
should be strong I'll look into it.


http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-12-07 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 42132.
loladiro added a comment.

Address David's concern about inner classes. David also suggested on IRC to 
propagate
the unique instantiation attribute down rather than walking the context chain to
check for the attribute. I'll try that out, but wanted to put up a known-good 
version
with all fixed first.


http://reviews.llvm.org/D13330

Files:
  include/clang/AST/ASTContext.h
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2373,6 +2373,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,46 @@
+// RUN: %clang -cc1 -std=c++14 -fsyntax-only -verify %s
+
+// Correct usage
+template 
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+template  T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+// Usages on non-templates
+float __attribute__((unique_instantiation)) notpi(2.71828182845904523536028747135); // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+struct __attribute__((unique_instantiation)) bar{}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+void __attribute__((unique_instantiation)) func() {} // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+// Usages that violate one of the conditions required conditions
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template  T pi1 = T(3.1415926535897932385);
+template __attribute__((unique_instantiation)) float pi1;  // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct  __attribute__((unique_instantiation(16))) foo6;// expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,69 @@
+// RUN: %clang -std=c++14 -emit-llvm -c -S -o - %s | FileCheck %s
+
+// CHECK: @_Z2piIfE = global float
+// CHECK-NOT: @_Z2piIfE = weak_odr global float
+template  T pi = T(3.1415926535897932385);
+extern template __attribute_

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-12-07 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 42137.
loladiro added a comment.

Propagate unique instantiation attribute to children rather than later trying 
to look through the DeclContexts to see if we're contained in one that has the 
attribute.


http://reviews.llvm.org/D13330

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  include/clang/Sema/Sema.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2373,6 +2373,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang -cc1 -std=c++14 -fsyntax-only -verify %s
+
+// Correct usage
+template 
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+// Usages on non-templates
+float __attribute__((unique_instantiation)) notpi(2.71828182845904523536028747135); // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+struct __attribute__((unique_instantiation)) bar {};// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+void __attribute__((unique_instantiation)) func() {}// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+// Usages that violate one of the conditions required conditions
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+T pi1 = T(3.1415926535897932385);
+template __attribute__((unique_instantiation)) float pi1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct __attribute__((unique_instantiation(16))) foo6; // expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang -std=c++14 -emit-llvm -c -S -o - %s | FileCheck %s
+
+// CHECK: @_Z2piIfE = global float
+// CHECK-NOT: @_Z2piIfE = weak_odr global float
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)

Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-12-11 Thread Keno Fischer via cfe-commits
loladiro added a comment.

@majnemer Do you like the new approach? Is there anything else to be done here?


http://reviews.llvm.org/D13330



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: [PATCH] D13330: Implement __attribute__((unique_instantiation))

2015-12-18 Thread Keno Fischer via cfe-commits
loladiro updated this revision to Diff 43218.
loladiro added a comment.

Rebased


http://reviews.llvm.org/D13330

Files:
  include/clang/Basic/Attr.td
  include/clang/Basic/AttrDocs.td
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/AttributeList.h
  include/clang/Sema/Sema.h
  lib/AST/ASTContext.cpp
  lib/CodeGen/CGVTables.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaDeclAttr.cpp
  lib/Sema/SemaDeclCXX.cpp
  lib/Sema/SemaTemplate.cpp
  test/CodeGenCXX/unique-instantiation.cpp
  test/SemaCXX/unique-instantiations.cpp
  utils/TableGen/ClangAttrEmitter.cpp

Index: utils/TableGen/ClangAttrEmitter.cpp
===
--- utils/TableGen/ClangAttrEmitter.cpp
+++ utils/TableGen/ClangAttrEmitter.cpp
@@ -2369,6 +2369,8 @@
 case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
 case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
 case Func | Var: return "ExpectedVariableOrFunction";
+case Func | Class:
+  return "ExpectedFunctionOrClass";
 
 // If not compiling for C++, the class portion does not apply.
 case Func | Var | Class:
Index: test/SemaCXX/unique-instantiations.cpp
===
--- /dev/null
+++ test/SemaCXX/unique-instantiations.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang -cc1 -std=c++14 -fsyntax-only -verify %s
+
+// Correct usage
+template 
+struct foo {};
+extern template struct __attribute__((unique_instantiation)) foo;
+template struct __attribute__((unique_instantiation)) foo;
+
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+// Usages on non-templates
+float __attribute__((unique_instantiation)) notpi(2.71828182845904523536028747135); // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+struct __attribute__((unique_instantiation)) bar {};// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+void __attribute__((unique_instantiation)) func() {}// expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+// Usages that violate one of the conditions required conditions
+template 
+struct foo1 {};
+template struct __attribute__((unique_instantiation)) foo1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+T pi1 = T(3.1415926535897932385);
+template __attribute__((unique_instantiation)) float pi1; // expected-error{{'unique_instantiation' attribute on an explicit instantiation requires a previous explicit instantiation declaration}}
+
+template 
+struct foo2 {};
+extern template struct foo2;// expected-note{{previous explicit instantiation is here}}
+template struct __attribute__((unique_instantiation)) foo2; // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo3 {};
+extern template struct __attribute__((unique_instantiation)) foo3; // expected-note{{previous explicit instantiation is here}}
+extern template struct foo3;   // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct __attribute__((unique_instantiation)) foo4 {}; // expected-error{{'unique_instantiation' attribute only applies to explicit template declarations or definitions}}
+
+template 
+struct foo5 {};
+extern template struct __attribute__((unique_instantiation)) foo5; // expected-note{{previous explicit instantiation is here}}
+template struct foo5;  // expected-error{{'unique_instantiation' attribute must be specified for all declarations and definitions of this explicit template instantiation}}
+
+template 
+struct foo6 {};
+extern template struct __attribute__((unique_instantiation(16))) foo6; // expected-error{{'unique_instantiation' attribute takes no arguments}}
Index: test/CodeGenCXX/unique-instantiation.cpp
===
--- /dev/null
+++ test/CodeGenCXX/unique-instantiation.cpp
@@ -0,0 +1,74 @@
+// RUN: %clang -std=c++14 -emit-llvm -c -S -o - %s | FileCheck %s
+
+// CHECK: @_Z2piIfE = global float
+// CHECK-NOT: @_Z2piIfE = weak_odr global float
+template 
+T pi = T(3.1415926535897932385);
+extern template __attribute__((unique_instantiation)) float pi;
+template __attribute__((unique_instantiation)) float pi;
+
+template 
+struct foo {
+  T x;
+  T getX() { return x; }
+  struct bar {
+T y;
+

Re: [PATCH] D13419: Fix several problems at the intersection of template instantiations and visibility

2015-12-19 Thread Keno Fischer via cfe-commits
loladiro added a comment.

bump again


Repository:
  rL LLVM

http://reviews.llvm.org/D13419



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][MinGW] Implement -mcrtdll option to switch crt choice (PR #149469)

2025-07-18 Thread Keno Fischer via cfe-commits

https://github.com/Keno created https://github.com/llvm/llvm-project/pull/149469

This implements the mingw `-mcrtdll` option recently added to gcc.
This option is useful for having the compiler be in charge of crt
version selection while only shipping a single copy of mingw for a
multi-ABI toolchain. That said, there are various ABI dependent compiler
libraries (e.g. libstdc++), so a certain degree of ABI awareness is
nevertheless required in order to use this option correctly.

See also #149434 (which this branch includes, since it touches the same code).

>From e3dd50c14f79dca0d28e482f707849c92ec0df76 Mon Sep 17 00:00:00 2001
From: Keno Fischer 
Date: Fri, 18 Jul 2025 01:02:00 +
Subject: [PATCH 1/2] [Driver][MinGW] Always put libc argument last, even if
 non-standard

I was attempting to build openblas with clang in msys2's `ucrt64`
environment (I'm aware of the `clang64` environment, but I wanted
libstdc++). The openblas link failed with the following:

```
clang -march=native -mtune=native -m64  -O2 -fno-asynchronous-unwind-tables -O2 
-DSMALL_MATRIX_OPT -DMS_ABI -DMAX_STACK_ALLOC=2048 -Wall -m64 
-DF_INTERFACE_GFORT -DDYNAMIC_ARCH -DSMP_SERVER -DNO_WARMUP 
-DMAX_CPU_NUMBER=512 -DMAX_PARALLEL_NUMBER=1 -DBUILD_SINGLE=1 -DBUILD_DOUBLE=1 
-DBUILD_COMPLEX=1 -DBUILD_COMPLEX16=1 -DVERSION=\"0.3.29\" -UASMNAME -UASMFNAME 
-UNAME -UCNAME -UCHAR_NAME -UCHAR_CNAME -DASMNAME= -DASMFNAME=_ -DNAME=_ 
-DCNAME= -DCHAR_NAME=\"_\" -DCHAR_CNAME=\"\" -DNO_AFFINITY -I..  
libopenblas64_.def dllinit.obj \
-shared -o ../libopenblas64_.dll -Wl,--out-implib,../libopenblas64_.dll.a \
-Wl,--whole-archive ../libopenblas64_p-r0.3.29.a -Wl,--no-whole-archive 
-LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0 
-LC:/msys64/ucrt64/bin/../lib/gcc 
-LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../x86_64-w64-mingw32/lib/../lib
 -LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../lib 
-LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../x86_64-w64-mingw32/lib
 -LC:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../..  
-lgfortran -lmingwex -lmsvcrt -lquadmath -lm -lpthread -lmingwex -lmsvcrt  
-defaultlib:advapi32 -lgfortran -defaultlib:advapi32 -lgfortran

C:/msys64/ucrt64/bin/ld: 
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-pseudo-reloc.o):
 in function `__report_error':
D:/W/B/src/mingw-w64/mingw-w64-crt/crt/pseudo-reloc.c:157:(.text+0x59): 
undefined reference to `abort'
C:/msys64/ucrt64/bin/ld: 
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-tlsthrd.o):
 in function `___w64_mingwthr_add_key_dtor':
D:/W/B/src/mingw-w64/mingw-w64-crt/crt/tlsthrd.c:48:(.text+0xa5): undefined 
reference to `calloc'
C:/msys64/ucrt64/bin/ld: 
C:/msys64/ucrt64/bin/../lib/gcc/x86_64-w64-mingw32/15.1.0/../../../../lib/libmingw32.a(lib64_libmingw32_a-pesect.o):
 in function `_FindPESectionByName':
D:/W/B/src/mingw-w64/mingw-w64-crt/crt/pesect.c:79:(.text+0xfd): undefined 
reference to `strncmp'
```

These symbols come from the `-lmingw32` dep that the driver added
and are ordinarily found in `-lmsvcrt`, which got skipped here,
because openblas passed `-lmsvcrt` explicitly. Since we always
add these libraries at the end here, I think that clang is "at fault"
(as opposed to a user or packaging mistake) and should have added some crt here.

To preserve the intent of letting the user override which crt is chosen,
duplicate the (first) user chosen crt `-l` into this position,
although we should perhaps consider an explicit `-mcrtdll` like gcc has as well.
---
 clang/lib/Driver/ToolChains/MinGW.cpp | 11 +--
 clang/test/Driver/mingw-msvcrt.c  |  8 
 2 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp 
b/clang/lib/Driver/ToolChains/MinGW.cpp
index 7d093d20b3dd9..58c59aa7f2237 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -85,11 +85,18 @@ void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
 
   CmdArgs.push_back("-lmoldname");
   CmdArgs.push_back("-lmingwex");
-  for (auto Lib : Args.getAllArgValues(options::OPT_l))
+  for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
 if (StringRef(Lib).starts_with("msvcr") ||
 StringRef(Lib).starts_with("ucrt") ||
-StringRef(Lib).starts_with("crtdll"))
+StringRef(Lib).starts_with("crtdll")) {
+  Lib = (llvm::Twine("-l") + Lib).str();
+  // Respect the user's chosen crt variant, but still provide it
+  // again as the last linker argument, because some of the libraries
+  // we added above may depend on it.
+  CmdArgs.push_back(Args.MakeArgStringRef(Lib));
   return;
+}
+  }
   CmdArgs.push_back("-lmsvcrt");
 }
 
diff --git a/clang/test/Driver/mingw-msvcrt.c b/clang/test/Driver/mingw-msvcrt.c
index 340ce1f57b0f8..e1648630476a0 100644
--- a/

[clang] [Driver][MinGW] Always put libc argument last, even if non-standard (PR #149434)

2025-07-17 Thread Keno Fischer via cfe-commits

Keno wrote:

> why not use lld?

It's how the toolchain happens to be configured, and we can't tell users of 
clang that they need to use lld if they want their builds to work, especially 
if they work fine with gcc.

https://github.com/llvm/llvm-project/pull/149434
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Driver][MinGW] Always put libc argument last, even if non-standard (PR #149434)

2025-07-29 Thread Keno Fischer via cfe-commits

https://github.com/Keno closed https://github.com/llvm/llvm-project/pull/149434
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits