[PATCH] D27800: Add overload of TransformToPotentiallyEvaluated for TypeSourceInfo

2017-01-22 Thread Paulo Matos via Phabricator via cfe-commits
pmatos updated this revision to Diff 85328.
pmatos added a comment.

Here's an updated patch including the test. Hope this is now ok for submission. 
Please accept my apologies with regards to the delaying in submitting this.


https://reviews.llvm.org/D27800

Files:
  include/clang/Sema/Sema.h
  lib/Sema/SemaExpr.cpp
  test/SemaCXX/pr31042.cpp


Index: test/SemaCXX/pr31042.cpp
===
--- test/SemaCXX/pr31042.cpp
+++ test/SemaCXX/pr31042.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -emit-obj 
-disable-free %s
+
+extern void abort (void);
+
+char a[1];
+
+void
+f1 (void)
+{
+  int i = 0;
+  int j = sizeof (typeof (*(char (*)[i])a));
+}
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -4028,6 +4028,10 @@
   }
 
   // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+  if (isUnevaluatedContext() && ExprKind == UETT_SizeOf &&
+  TInfo->getType()->isVariablyModifiedType())
+TInfo = TransformToPotentiallyEvaluated(TInfo);
+  
   return new (Context) UnaryExprOrTypeTraitExpr(
   ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd());
 }
@@ -13088,6 +13092,17 @@
   return TransformToPE(*this).TransformExpr(E);
 }
 
+
+TypeSourceInfo *Sema::TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo) {
+  assert(isUnevaluatedContext() &&
+ "Should only transform unevaluated expressions");
+  ExprEvalContexts.back().Context =
+  ExprEvalContexts[ExprEvalContexts.size()-2].Context;
+  if (isUnevaluatedContext())
+return TInfo;
+  return TransformToPE(*this).TransformType(TInfo);
+}
+
 void
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
   Decl *LambdaContextDecl,
Index: include/clang/Sema/Sema.h
===
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -3784,6 +3784,7 @@
   void DiscardCleanupsInEvaluationContext();
 
   ExprResult TransformToPotentiallyEvaluated(Expr *E);
+  TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
   ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
 
   ExprResult ActOnConstantExpression(ExprResult Res);


Index: test/SemaCXX/pr31042.cpp
===
--- test/SemaCXX/pr31042.cpp
+++ test/SemaCXX/pr31042.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fsyntax-only -emit-obj -disable-free %s
+
+extern void abort (void);
+
+char a[1];
+
+void
+f1 (void)
+{
+  int i = 0;
+  int j = sizeof (typeof (*(char (*)[i])a));
+}
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -4028,6 +4028,10 @@
   }
 
   // C99 6.5.3.4p4: the type (an unsigned integer type) is size_t.
+  if (isUnevaluatedContext() && ExprKind == UETT_SizeOf &&
+  TInfo->getType()->isVariablyModifiedType())
+TInfo = TransformToPotentiallyEvaluated(TInfo);
+  
   return new (Context) UnaryExprOrTypeTraitExpr(
   ExprKind, TInfo, Context.getSizeType(), OpLoc, R.getEnd());
 }
@@ -13088,6 +13092,17 @@
   return TransformToPE(*this).TransformExpr(E);
 }
 
+
+TypeSourceInfo *Sema::TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo) {
+  assert(isUnevaluatedContext() &&
+ "Should only transform unevaluated expressions");
+  ExprEvalContexts.back().Context =
+  ExprEvalContexts[ExprEvalContexts.size()-2].Context;
+  if (isUnevaluatedContext())
+return TInfo;
+  return TransformToPE(*this).TransformType(TInfo);
+}
+
 void
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
   Decl *LambdaContextDecl,
Index: include/clang/Sema/Sema.h
===
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -3784,6 +3784,7 @@
   void DiscardCleanupsInEvaluationContext();
 
   ExprResult TransformToPotentiallyEvaluated(Expr *E);
+  TypeSourceInfo *TransformToPotentiallyEvaluated(TypeSourceInfo *TInfo);
   ExprResult HandleExprEvaluationContextForTypeof(Expr *E);
 
   ExprResult ActOnConstantExpression(ExprResult Res);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


Re: r291318 - PR23135: Don't instantiate constexpr functions referenced in unevaluated operands where possible.

2017-01-22 Thread Mehdi Amini via cfe-commits
Hi Richard,

I have a link failure in WebKit following this patch, the move-assign operator 
for an nested class isn’t emitted (IRGen) in some context where it is needed.

I’m working on running creduce the test-case which is pretty large, but in case 
it rings a bell, I let you know already.

— 
Mehdi

> On Jan 6, 2017, at 4:48 PM, Richard Smith via cfe-commits 
>  wrote:
> 
> Author: rsmith
> Date: Fri Jan  6 18:48:55 2017
> New Revision: 291318
> 
> URL: http://llvm.org/viewvc/llvm-project?rev=291318=rev
> Log:
> PR23135: Don't instantiate constexpr functions referenced in unevaluated 
> operands where possible.
> 
> This implements something like the current direction of DR1581: we use a 
> narrow
> syntactic check to determine the set of places where a constant expression
> could be evaluated, and only instantiate a constexpr function or variable if
> it's referenced in one of those contexts, or is odr-used.
> 
> It's not yet clear whether this is the right set of syntactic locations; we
> currently consider all contexts within templates that would result in odr-uses
> after instantiation, and contexts within list-initialization (narrowing
> conversions take another victim...), as requiring instantiation. We could in
> principle restrict the former cases more (only const integral / reference
> variable initializers, and contexts in which a constant expression is 
> required,
> perhaps). However, this is sufficient to allow us to accept libstdc++ code,
> which relies on GCC's behavior (which appears to be somewhat similar to this
> approach).
> 
> Modified:
>cfe/trunk/include/clang/Sema/Sema.h
>cfe/trunk/lib/Parse/ParseInit.cpp
>cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>cfe/trunk/lib/Sema/SemaExpr.cpp
>cfe/trunk/lib/Sema/SemaExprMember.cpp
>cfe/trunk/lib/Sema/SemaInit.cpp
>cfe/trunk/lib/Sema/SemaLambda.cpp
>cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp
>cfe/trunk/test/CXX/temp/temp.param/p5.cpp
>cfe/trunk/test/SemaCXX/constant-expression-cxx11.cpp
>cfe/trunk/test/SemaCXX/implicit-exception-spec.cpp
>cfe/trunk/test/SemaCXX/member-init.cpp
>cfe/trunk/test/SemaTemplate/constexpr-instantiate.cpp
>cfe/trunk/test/SemaTemplate/default-arguments-cxx0x.cpp
>cfe/trunk/test/SemaTemplate/instantiate-init.cpp
> 
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=291318=291317=291318=diff
> ==
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Fri Jan  6 18:48:55 2017
> @@ -807,6 +807,12 @@ public:
> /// run time.
> Unevaluated,
> 
> +/// \brief The current expression occurs within a braced-init-list within
> +/// an unevaluated operand. This is mostly like a regular unevaluated
> +/// context, except that we still instantiate constexpr functions that 
> are
> +/// referenced here so that we can perform narrowing checks correctly.
> +UnevaluatedList,
> +
> /// \brief The current expression occurs within a discarded statement.
> /// This behaves largely similarly to an unevaluated operand in preventing
> /// definitions from being required, but not in other ways.
> @@ -899,7 +905,8 @@ public:
> MangleNumberingContext (ASTContext );
> 
> bool isUnevaluated() const {
> -  return Context == Unevaluated || Context == UnevaluatedAbstract;
> +  return Context == Unevaluated || Context == UnevaluatedAbstract ||
> + Context == UnevaluatedList;
> }
>   };
> 
> @@ -10194,6 +10201,22 @@ public:
> IsDecltype);
>   }
> 
> +  enum InitListTag { InitList };
> +  EnterExpressionEvaluationContext(Sema , InitListTag,
> +   bool ShouldEnter = true)
> +  : Actions(Actions), Entered(false) {
> +// In C++11 onwards, narrowing checks are performed on the contents of
> +// braced-init-lists, even when they occur within unevaluated operands.
> +// Therefore we still need to instantiate constexpr functions used in 
> such
> +// a context.
> +if (ShouldEnter && Actions.isUnevaluatedContext() &&
> +Actions.getLangOpts().CPlusPlus11) {
> +  Actions.PushExpressionEvaluationContext(Sema::UnevaluatedList, nullptr,
> +  false);
> +  Entered = true;
> +}
> +  }
> +
>   ~EnterExpressionEvaluationContext() {
> if (Entered)
>   Actions.PopExpressionEvaluationContext();
> 
> Modified: cfe/trunk/lib/Parse/ParseInit.cpp
> URL: 
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseInit.cpp?rev=291318=291317=291318=diff
> ==
> --- cfe/trunk/lib/Parse/ParseInit.cpp (original)
> +++ cfe/trunk/lib/Parse/ParseInit.cpp Fri Jan  6 18:48:55 

[PATCH] D28080: [Docs][OpenCL] Added OpenCL feature description to user manual.

2017-01-22 Thread Pekka Jääskeläinen via Phabricator via cfe-commits
pekka.jaaskelainen added a comment.

In https://reviews.llvm.org/D28080#651732, @Anastasia wrote:

> @pekka.jaaskelainen, I just compiled the release 4.0 branch and it all works 
> for me as expected:
>  clang -cc1 -triple spir64-unknown-unknown test.cl
>  clang  -target spir64-unknown-unknown test.cl


Yes, that seems to work.

The problem was confusion with the frontend flag parameter. With the -cc1 it 
switches all parameters to
the frontend mode, not only the next one (like -Xclang does).

When I pass -Xclang before -cc1, it fails, if after, it fails also, but 
differently:

  $ clang -cc1 -triple spir64-unknown-unknown -Xclang -finclude-default-header 
~/temp/local.cl
  error: unknown argument: '-Xclang'
  $ clang -Xclang -finclude-default-header -cc1 -triple spir64-unknown-unknown 
~/temp/local.cl
  clang-4.0: error: unknown argument: '-cc1'
  clang-4.0: error: unknown argument: '-triple'
  clang-4.0: error: no such file or directory: 'spir64-unknown-unknown'

(I should pass -finclude-default-header after -cc1 without -Xclang then it 
works, but I think also the
latter version should work, no?)
Also, I cannot add -S (even with -emit-llvm), then it complains about a missing 
target:

  $ clang -cc1 -triple spir64-unknown-unknown ~/temp/local.cl -S
  error: unable to create target: 'No available targets are compatible with 
this triple.'

I think -S used to work with -emit-llvm as a switch to output LLVM text instead 
of bitcode, but now it seems to
output text by default so it should not be used. Is there are reason to 
use/document the -cc1 -triple instead of
-target here? Also, for me the command without -emit-llvm doesn't output 
anything.


https://reviews.llvm.org/D28080



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


[PATCH] D28983: clang-format: remove tests that assume no config file will be found as this is not always the case

2017-01-22 Thread Mikael Holmén via Phabricator via cfe-commits
uabelho added a comment.

Great! This patch solves the problems we saw. Thanks!


https://reviews.llvm.org/D28983



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


[PATCH] D28955: [analyzer] Enable support for symbolic extension/truncation

2017-01-22 Thread Dominic Chen via Phabricator via cfe-commits
ddcc updated this revision to Diff 85316.
ddcc added a comment.

Rebase


https://reviews.llvm.org/D28955

Files:
  include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
  include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  lib/StaticAnalyzer/Checkers/BoolAssignmentChecker.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
  lib/StaticAnalyzer/Core/Store.cpp
  test/Analysis/dead-stores.m
  test/Analysis/explain-svals.cpp
  test/Analysis/malloc.c
  test/Analysis/misc-ps-eager-assume.m
  test/Analysis/std-c-library-functions.c

Index: test/Analysis/std-c-library-functions.c
===
--- test/Analysis/std-c-library-functions.c
+++ test/Analysis/std-c-library-functions.c
@@ -146,7 +146,7 @@
 void test_isgraph_isprint(int x) {
   char y = x;
   if (isgraph(y))
-clang_analyzer_eval(isprint(x)); // expected-warning{{TRUE}}
+clang_analyzer_eval(isprint(y)); // expected-warning{{TRUE}}
 }
 
 int isdigit(int);
Index: test/Analysis/misc-ps-eager-assume.m
===
--- test/Analysis/misc-ps-eager-assume.m
+++ test/Analysis/misc-ps-eager-assume.m
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -verify -fblocks %s -analyzer-eagerly-assume
-// expected-no-diagnostics
 
 // Delta-reduced header stuff (needed for test cases).
 typedef signed char BOOL;
@@ -56,7 +55,7 @@
 void handle_symbolic_cast_in_condition(void) {
   NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
 
-  BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"];
+  BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"]; // expected-warning {{Assignment of a non-Boolean value}}
   NSMutableArray* array = needsAnArray ? [[NSMutableArray alloc] init] : 0;
   if(needsAnArray)
 [array release];
Index: test/Analysis/malloc.c
===
--- test/Analysis/malloc.c
+++ test/Analysis/malloc.c
@@ -1656,13 +1656,13 @@
 void testOffsetPassedToStrlen() {
   char * string = malloc(sizeof(char)*10);
   string += 1;
-  int length = strlen(string); // expected-warning {{Potential leak of memory pointed to by 'string'}}
+  size_t length = strlen(string); // expected-warning {{Potential leak of memory pointed to by 'string'}}
 }
 
 void testOffsetPassedToStrlenThenFree() {
   char * string = malloc(sizeof(char)*10);
   string += 1;
-  int length = strlen(string);
+  size_t length = strlen(string);
   free(string); // expected-warning {{Argument to free() is offset by 1 byte from the start of memory allocated by malloc()}}
 }
 
@@ -1705,7 +1705,7 @@
 }
 
 char *dupstrNoWarn(const char *s) {
-  const int len = strlen(s);
+  const size_t len = strlen(s);
   char *p = (char*) smallocNoWarn(len + 1);
   strcpy(p, s); // no-warning
   return p;
@@ -1721,7 +1721,7 @@
 }
 
 char *dupstrWarn(const char *s) {
-  const int len = strlen(s);
+  const size_t len = strlen(s);
   char *p = (char*) smallocWarn(len + 1);
   strcpy(p, s); // expected-warning{{String copy function overflows destination buffer}}
   return p;
Index: test/Analysis/explain-svals.cpp
===
--- test/Analysis/explain-svals.cpp
+++ test/Analysis/explain-svals.cpp
@@ -41,11 +41,11 @@
 
 void test_2(char *ptr, int ext) {
   clang_analyzer_explain((void *) "asdf"); // expected-warning-re^pointer to element of type 'char' with index 0 of string literal "asdf"$
-  clang_analyzer_explain(strlen(ptr)); // expected-warning-re^metadata of type 'unsigned long' tied to pointee of argument 'ptr'$
+  clang_analyzer_explain(strlen(ptr)); // expected-warning-re^cast of type 'int' of metadata of type 'unsigned long' tied to pointee of argument 'ptr'$
   clang_analyzer_explain(conjure()); // expected-warning-re^symbol of type 'int' conjured at statement 'conjure\(\)'$
   clang_analyzer_explain(glob); // expected-warning-re^value derived from \(symbol of type 'int' conjured at statement 'conjure\(\)'\) for global variable 'glob'$
   clang_analyzer_explain(glob_ptr); // expected-warning-re^value derived from \(symbol of type 'int' conjured at statement 'conjure\(\)'\) for global variable 'glob_ptr'$
-  clang_analyzer_explain(clang_analyzer_getExtent(ptr)); // expected-warning-re^extent of pointee of argument 'ptr'$
+  clang_analyzer_explain(clang_analyzer_getExtent(ptr)); // expected-warning-re^cast of type 'int' of extent of pointee of argument 'ptr'$
   int *x = new int[ext];
   clang_analyzer_explain(x); // expected-warning-re^pointer to element of type 'int' with index 0 of heap segment that starts at symbol of type 'int \*' conjured at statement 'new int \[ext\]'$
   // Sic! What gets computed is the extent of the element-region.
Index: test/Analysis/dead-stores.m

[PATCH] D28953: [analyzer] Eliminate analyzer limitations on symbolic constraint generation

2017-01-22 Thread Dominic Chen via Phabricator via cfe-commits
ddcc updated this revision to Diff 85314.
ddcc added a comment.

Rebase


https://reviews.llvm.org/D28953

Files:
  include/clang/StaticAnalyzer/Checkers/SValExplainer.h
  lib/StaticAnalyzer/Core/SValBuilder.cpp
  lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
  test/Analysis/bitwise-ops.c
  test/Analysis/conditional-path-notes.c
  test/Analysis/explain-svals.cpp
  test/Analysis/std-c-library-functions.c

Index: test/Analysis/std-c-library-functions.c
===
--- test/Analysis/std-c-library-functions.c
+++ test/Analysis/std-c-library-functions.c
@@ -57,8 +57,7 @@
   size_t y = fread(buf, sizeof(int), 10, fp);
   clang_analyzer_eval(y <= 10); // expected-warning{{TRUE}}
   size_t z = fwrite(buf, sizeof(int), y, fp);
-  // FIXME: should be TRUE once symbol-symbol constraint support is improved.
-  clang_analyzer_eval(z <= y); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(z <= y); // expected-warning{{TRUE}}
 }
 
 ssize_t getline(char **, size_t *, FILE *);
Index: test/Analysis/explain-svals.cpp
===
--- test/Analysis/explain-svals.cpp
+++ test/Analysis/explain-svals.cpp
@@ -69,7 +69,7 @@
   static int stat;
   clang_analyzer_explain(x + 1); // expected-warning-re^\(argument 'x'\) \+ 1$
   clang_analyzer_explain(1 + y); // expected-warning-re^\(argument 'y'\) \+ 1$
-  clang_analyzer_explain(x + y); // expected-warning-re^unknown value$
+  clang_analyzer_explain(x + y); // expected-warning-re^\(argument 'x'\) \+ \(argument 'y'\)$
   clang_analyzer_explain(z); // expected-warning-re^undefined value$
   clang_analyzer_explain(); // expected-warning-re^pointer to local variable 'z'$
   clang_analyzer_explain(stat); // expected-warning-re^signed 32-bit integer '0'$
Index: test/Analysis/conditional-path-notes.c
===
--- test/Analysis/conditional-path-notes.c
+++ test/Analysis/conditional-path-notes.c
@@ -77,7 +77,8 @@
 
 void testNonDiagnosableBranchArithmetic(int a, int b) {
   if (a - b) {
-// expected-note@-1 {{Taking true branch}}
+// expected-note@-1 {{Assuming the condition is true}}
+// expected-note@-2 {{Taking true branch}}
 *(volatile int *)0 = 1; // expected-warning{{Dereference of null pointer}}
 // expected-note@-1 {{Dereference of null pointer}}
   }
@@ -1573,12 +1574,75 @@
 // CHECK-NEXT: end
 // CHECK-NEXT:  
 // CHECK-NEXT:   
-// CHECK-NEXT:line81
+// CHECK-NEXT:line79
+// CHECK-NEXT:col7
+// CHECK-NEXT:file0
+// CHECK-NEXT:   
+// CHECK-NEXT:   
+// CHECK-NEXT:line79
+// CHECK-NEXT:col7
+// CHECK-NEXT:file0
+// CHECK-NEXT:   
+// CHECK-NEXT:  
+// CHECK-NEXT:
+// CHECK-NEXT:   
+// CHECK-NEXT: 
+// CHECK-NEXT: 
+// CHECK-NEXT:  kindevent
+// CHECK-NEXT:  location
+// CHECK-NEXT:  
+// CHECK-NEXT:   line79
+// CHECK-NEXT:   col7
+// CHECK-NEXT:   file0
+// CHECK-NEXT:  
+// CHECK-NEXT:  ranges
+// CHECK-NEXT:  
+// CHECK-NEXT:
+// CHECK-NEXT: 
+// CHECK-NEXT:  line79
+// CHECK-NEXT:  col7
+// CHECK-NEXT:  file0
+// CHECK-NEXT: 
+// CHECK-NEXT: 
+// CHECK-NEXT:  line79
+// CHECK-NEXT:  col11
+// CHECK-NEXT:  file0
+// CHECK-NEXT: 
+// CHECK-NEXT:
+// CHECK-NEXT:  
+// CHECK-NEXT:  depth0
+// CHECK-NEXT:  extended_message
+// CHECK-NEXT:  Assuming the condition is true
+// CHECK-NEXT:  message
+// CHECK-NEXT:  Assuming the condition is true
+// CHECK-NEXT: 
+// CHECK-NEXT: 
+// CHECK-NEXT:  kindcontrol
+// CHECK-NEXT:  edges
+// CHECK-NEXT:   
+// CHECK-NEXT:
+// CHECK-NEXT: start
+// CHECK-NEXT:  
+// CHECK-NEXT:   
+// CHECK-NEXT:line79
+// CHECK-NEXT:col7
+// CHECK-NEXT:file0
+// CHECK-NEXT:   
+// CHECK-NEXT:   
+// CHECK-NEXT:line79
+// CHECK-NEXT:col7
+// CHECK-NEXT:file0
+// CHECK-NEXT:   
+// CHECK-NEXT:  
+// CHECK-NEXT: end
+// CHECK-NEXT:  
+// CHECK-NEXT:   
+// CHECK-NEXT:line82
 // CHECK-NEXT:col5
 // CHECK-NEXT:file0
 // CHECK-NEXT:   
 // CHECK-NEXT:   
-// CHECK-NEXT:line81
+// CHECK-NEXT:line82
 // CHECK-NEXT:col5
 // CHECK-NEXT:file0
 // CHECK-NEXT:   
@@ -1594,25 +1658,25 @@
 // CHECK-NEXT: start
 // CHECK-NEXT:  
 // CHECK-NEXT:   
-// CHECK-NEXT:line81
+// CHECK-NEXT:line82
 // CHECK-NEXT:col5
 // CHECK-NEXT:file0
 // CHECK-NEXT:   
 // 

[PATCH] D28954: [analyzer] Add support for symbolic float expressions

2017-01-22 Thread Dominic Chen via Phabricator via cfe-commits
ddcc updated this revision to Diff 85315.
ddcc added a comment.

Rebase


https://reviews.llvm.org/D28954

Files:
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h
  include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
  include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def
  include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
  include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
  include/clang/StaticAnalyzer/Core/PathSensitive/Symbols.def
  lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
  lib/StaticAnalyzer/Checkers/CMakeLists.txt
  lib/StaticAnalyzer/Checkers/FloatingPointMath.cpp
  lib/StaticAnalyzer/Core/BasicValueFactory.cpp
  lib/StaticAnalyzer/Core/Environment.cpp
  lib/StaticAnalyzer/Core/ProgramState.cpp
  lib/StaticAnalyzer/Core/RegionStore.cpp
  lib/StaticAnalyzer/Core/SValBuilder.cpp
  lib/StaticAnalyzer/Core/SVals.cpp
  lib/StaticAnalyzer/Core/SimpleConstraintManager.cpp
  lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
  lib/StaticAnalyzer/Core/SymbolManager.cpp
  lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
  test/Analysis/diagnostics/macros.cpp
  test/Analysis/float-rules.c
  test/Analysis/float.c
  test/Analysis/inline.cpp
  test/Analysis/operator-calls.cpp

Index: test/Analysis/operator-calls.cpp
===
--- test/Analysis/operator-calls.cpp
+++ test/Analysis/operator-calls.cpp
@@ -81,8 +81,8 @@
   void test(int coin) {
 // Force a cache-out when we try to conjure a temporary region for the operator call.
 // ...then, don't crash.
-clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{UNKNOWN}}
-clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{UNKNOWN}}
+clang_analyzer_eval(+(coin ? getSmallOpaque() : getSmallOpaque())); // expected-warning{{TRUE}}
+clang_analyzer_eval(+(coin ? getLargeOpaque() : getLargeOpaque())); // expected-warning{{TRUE}}
   }
 }
 
Index: test/Analysis/inline.cpp
===
--- test/Analysis/inline.cpp
+++ test/Analysis/inline.cpp
@@ -285,11 +285,11 @@
   }
 
   void testFloatReference() {
-clang_analyzer_eval(defaultFloatReference(1) == -1); // expected-warning{{UNKNOWN}}
-clang_analyzer_eval(defaultFloatReference() == -42); // expected-warning{{UNKNOWN}}
+clang_analyzer_eval(defaultFloatReference(1) == -1); // expected-warning{{TRUE}}
+clang_analyzer_eval(defaultFloatReference() == -42); // expected-warning{{TRUE}}
 
-clang_analyzer_eval(defaultFloatReferenceZero(1) == -1); // expected-warning{{UNKNOWN}}
-clang_analyzer_eval(defaultFloatReferenceZero() == 0); // expected-warning{{UNKNOWN}}
+clang_analyzer_eval(defaultFloatReferenceZero(1) == -1); // expected-warning{{TRUE}}
+clang_analyzer_eval(defaultFloatReferenceZero() == 0); // expected-warning{{TRUE}}
   }
 
   char defaultString(const char *s = "abc") {
Index: test/Analysis/float.c
===
--- /dev/null
+++ test/Analysis/float.c
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core.builtin,debug.ExprInspection -verify %s
+// REQUIRES: z3
+
+void clang_analyzer_eval(int);
+
+void float1() {
+  float z1 = 0.0, z2 = -0.0;
+  clang_analyzer_eval(z1 == z2); // expected-warning{{TRUE}}
+}
+
+void float2(float a, float b) {
+  clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(a != b); // expected-warning{{UNKNOWN}}
+}
+
+void float3(float a, float b) {
+  if (__builtin_isnan(a) || __builtin_isnan(b) || a < b) {
+clang_analyzer_eval(a > b); // expected-warning{{FALSE}}
+clang_analyzer_eval(a == b); // expected-warning{{FALSE}}
+return;
+  }
+  clang_analyzer_eval(a >= b); // expected-warning{{TRUE}}
+  clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}}
+}
+
+void float4(float a) {
+  if (__builtin_isnan(a) || a < 0.0f)
+return;
+  clang_analyzer_eval(a >= 0.0Q); // expected-warning{{TRUE}}
+  clang_analyzer_eval(a >= 0.0F); // expected-warning{{TRUE}}
+  clang_analyzer_eval(a >= 0.0); // expected-warning{{TRUE}}
+  clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}}
+}
+
+void float5() {
+  double value = 1.0;
+  double pinf = __builtin_inf();
+  double ninf = -__builtin_inf();
+  double nan = __builtin_nan("");
+
+  /* NaN */
+  clang_analyzer_eval(__builtin_isnan(value)); // expected-warning{{FALSE}}
+  clang_analyzer_eval(__builtin_isnan(nan)); // expected-warning{{TRUE}}
+
+  clang_analyzer_eval(__builtin_isnan(0.0 / 0.0)); // expected-warning{{TRUE}}
+  clang_analyzer_eval(__builtin_isnan(pinf / ninf)); // expected-warning{{TRUE}}
+  clang_analyzer_eval(__builtin_isnan(pinf / pinf)); // expected-warning{{TRUE}}
+  clang_analyzer_eval(__builtin_isnan(ninf / 

[PATCH] D28952: [analyzer] Add new Z3 constraint manager backend

2017-01-22 Thread Dominic Chen via Phabricator via cfe-commits
ddcc added a comment.

I'd like to note that one of the main challenges with this implementation was 
needing to perform type reinference and implicit casting within the constraint 
manager, since the constraints are sometimes implicit. (e.g. `(int) x` instead 
of `x == 0`). It also didn't help that the Sema methods for handling type 
conversion aren't directly usable.

> Can you talk a bit about your motivation for working on this project and what 
> your goals are?

The original goal was to add support for symbolic execution on floating-point 
types, and analyze some real-world programs to look for interesting bugs. 
Unfortunately, it turns out that most floating-point bugs in the past tend to 
originate lower in the compiler toolchain, within the register allocator (e.g. 
non-determinism involving x87 FPU 80-bit registers), intermediate optimization 
passes (see Alive-FP), string conversions involving floating-point types (which 
may be too complex to model easily), or unexpected interactions between various 
1st/3rd-party code when modifying the C99 thread-local floating-point 
environment (from fpenv.h). But the latter isn't really well modeled by 
Clang/LLVM, resulting in false-positives when real-world program use 
floating-point exception handlers to catch underflow/overflow/etc conditions. 
There's also the floating-point rounding mode that can be changed at runtime, 
but again, it's not something that's currently modeled by Clang/LLVM. I have 
seen a set of patches on the mailing list (by Sergey, I believe) that improve 
support for this, but to my knowledge they haven't been merged yet.

> Have you compared the performance when using Z3 vs the current builtin 
> solver? I saw that you mention performance issues on large codebases, but 
> could you give some specific numbers of the tradeoffs between performance, 
> code coverage, and the quality of reported bugs. (One very rough idea to use 
> a stronger solver while still keeping the analyzer performant would be to 
> only use it for false positive refutation.)

On a virtualized i5-2500k system, I get the following performance numbers on 
the testsuite, with a Clang/LLVM BUILD_SHARED_LIBS release build and Z3 
https://github.com/z3prover/z3/commits/1bfd09e16bd9aaeae8a6b2841a2e8da615fdcda4 
(post-4.5.0):
RangeConstraintManager: 13.46 sec
Z3ConstraintManager (plugin): 416.5 sec
Z3ConstraintManager (built-in): 414.6 sec
Z3ConstraintManager (built-in, with below changes): 303.92 sec
Z3ConstraintManager (built-in, with below changes and no simplify): 250.71 sec

In addition to the caveats above, the other more practical problem is that the 
performance is really bad on medium to large-sized codebases. I did some 
testing on gmp, mpfr, libvpx, daala, libsdl, and opus, and for all of these 
projects, with static analysis enabled (via scan-build, and a release mode 
Clang/LLVM), the builds (in parallel) wouldn't finish even after a week on a 
Xeon E5-2620v3 workstation, and there were a lot of false positives that were 
hard to dig through. I did end up finding and reporting one bug in mpfr 
(https://sympa.inria.fr/sympa/arc/mpfr/2017-01/msg00012.html), but it's not 
floating-point related, and I didn't check if it could also be found by vanilla 
Clang/LLVM. With regards to the performance, I believe that this was due to 
multiple factors, and correct me if I'm wrong:

1. The Z3 solver timeout is set to 15 sec, which is probably too large (for an 
example that fails, see https://github.com/Z3Prover/z3/issues/834). But when 
timeouts do occur, they can cause runtime failures in the static analyzer: e.g. 
the assertion to avoid overconstrained states (in ConstraintManager.h), or 
underconstrained states (in BugReporterVisitors.cpp).
2. The symbolic expression complexity parameter (`MaxComp`) is set to 1, 
which is probably also too large. I'm guessing that overly-complex constraints 
are being generated, which can't be meaningfully solved and just bog down the 
analyzer.
3. Within the analyzer, states are removed and iterated one-by-one off of the 
internal worklist, in a single-thread in a single-process. I'm guessing that 
this means the analyzer ends up waiting on Z3 most of the time. This is also 
why I started running analyses in parallel on different projects, because the 
analysis for each project would occupy just one core.
4. The same queries end up being sent to the constraint manager despite no 
meaningful change in the program state, through either `assume()` or 
`getSymVal()`. But for expensive queries, this means that a lot of time/compute 
is just wasted. I think this could be improved by implementing a SMT query 
cache, and potentially by only adding relevant constraints to the solver state. 
I actually have a draft attempt at a simple query cache implementation 
(https://github.com/ddcc/clang/commit/e0236ff8f7b9c16dd29e8529420ab14b4309c3e6),
 but it's very hacky, isn't entirely memory-safe, caused some testsuite 
failures, and I ran 

[PATCH] D28952: [analyzer] Add new Z3 constraint manager backend

2017-01-22 Thread Dominic Chen via Phabricator via cfe-commits
ddcc updated this revision to Diff 85313.
ddcc added a comment.

Convert to plugin, add move/assignment constructor, avoid Z3_simplify(), use 
Z3_mk_simple_solver(), generate logical and of all constraints in solver


https://reviews.llvm.org/D28952

Files:
  CMakeLists.txt
  cmake/modules/FindZ3.cmake
  include/clang/Config/config.h.cmake
  include/clang/StaticAnalyzer/Core/Analyses.def
  include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h
  lib/StaticAnalyzer/Core/CMakeLists.txt
  lib/StaticAnalyzer/Core/Z3ConstraintManager.cpp
  test/Analysis/bool-assignment.c
  test/Analysis/expr-inspection.c
  test/Analysis/ptr-arith.c
  test/Analysis/unsupported-types.c
  test/lit.site.cfg.in

Index: test/lit.site.cfg.in
===
--- test/lit.site.cfg.in
+++ test/lit.site.cfg.in
@@ -15,6 +15,7 @@
 config.target_triple = "@TARGET_TRIPLE@"
 config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
 config.have_zlib = "@HAVE_LIBZ@"
+config.have_z3 = "@CLANG_HAVE_Z3@"
 config.clang_arcmt = @ENABLE_CLANG_ARCMT@
 config.clang_default_cxx_stdlib = "@CLANG_DEFAULT_CXX_STDLIB@"
 config.clang_staticanalyzer = @ENABLE_CLANG_STATIC_ANALYZER@
Index: test/Analysis/unsupported-types.c
===
--- /dev/null
+++ test/Analysis/unsupported-types.c
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -triple x86_64-unknown-linux -verify %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -triple powerpc64-linux-gnu -verify %s
+
+#define _Complex_I  (__extension__ 1.0iF)
+
+void clang_analyzer_eval(int);
+
+void complex_float(double _Complex x, double _Complex y) {
+  clang_analyzer_eval(x == y); // expected-warning{{UNKNOWN}}
+  if (x != 1.0 + 3.0 * _Complex_I && y != 1.0 - 4.0 * _Complex_I)
+return
+  clang_analyzer_eval(x == y); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(x + y == 2.0 - 1.0 * _Complex_I); // expected-warning{{UNKNOWN}}
+}
+
+void complex_int(int _Complex x, int _Complex y) {
+  clang_analyzer_eval(x == y); // expected-warning{{UNKNOWN}}
+  if (x != 1.0 + 3.0 * _Complex_I && y != 1.0 - 4.0 * _Complex_I)
+return
+  clang_analyzer_eval(x == y); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(x + y == 2.0 - 1.0 * _Complex_I); // expected-warning{{UNKNOWN}}
+}
+
+void longdouble_float(long double x, long double y) {
+  clang_analyzer_eval(x == y); // expected-warning{{UNKNOWN}}
+  if (x != 0.0L && y != 1.0L)
+return
+  clang_analyzer_eval(x == y); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(x + y == 1.0L); // expected-warning{{UNKNOWN}}
+}
Index: test/Analysis/ptr-arith.c
===
--- test/Analysis/ptr-arith.c
+++ test/Analysis/ptr-arith.c
@@ -255,30 +255,24 @@
 void zero_implies_reversed_equal(int *lhs, int *rhs) {
   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{UNKNOWN}}
   if ((rhs - lhs) == 0) {
-// FIXME: Should be FALSE.
-clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}}
-// FIXME: Should be TRUE.
-clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
+clang_analyzer_eval(rhs != lhs); // expected-warning{{FALSE}}
+clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}}
 return;
   }
   clang_analyzer_eval((rhs - lhs) == 0); // expected-warning{{FALSE}}
-  // FIXME: Should be FALSE.
-  clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
-  // FIXME: Should be TRUE.
-  clang_analyzer_eval(rhs != lhs); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}}
+  clang_analyzer_eval(rhs != lhs); // expected-warning{{TRUE}}
 }
 
 void canonical_equal(int *lhs, int *rhs) {
   clang_analyzer_eval(lhs == rhs); // expected-warning{{UNKNOWN}}
   if (lhs == rhs) {
-// FIXME: Should be TRUE.
-clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
+clang_analyzer_eval(rhs == lhs); // expected-warning{{TRUE}}
 return;
   }
   clang_analyzer_eval(lhs == rhs); // expected-warning{{FALSE}}
 
-  // FIXME: Should be FALSE.
-  clang_analyzer_eval(rhs == lhs); // expected-warning{{UNKNOWN}}
+  clang_analyzer_eval(rhs == lhs); // expected-warning{{FALSE}}
 }
 
 void compare_element_region_and_base(int *p) {
Index: test/Analysis/expr-inspection.c
===
--- test/Analysis/expr-inspection.c
+++ test/Analysis/expr-inspection.c
@@ -19,4 +19,4 @@
 
 // CHECK: Expressions:
 // CHECK-NEXT: clang_analyzer_printState : {clang_analyzer_printState}
-// CHECK-NEXT: Ranges are empty.
+// CHECK-NEXT: {{(Ranges are empty)|(Constraints:[[:space:]]*$)}}
Index: test/Analysis/bool-assignment.c
===
--- 

[PATCH] D29001: [Modules] Fallback to building the module if a timeout occurs

2017-01-22 Thread Bruno Cardoso Lopes via Phabricator via cfe-commits
bruno created this revision.
Herald added a subscriber: fhahn.

After https://reviews.llvm.org/D28299 gets in, clang will use PCMCache to 
manage memory buffers for pcm files. This means the lock file manager isn't 
needed for correctness anymore, but only as an optimization: clang waits for 
other processes to finish up building a module if they are already doing it.

Emit remark instead of errors to notify users when a timeout occures and 
actually build the module in case that happens.


https://reviews.llvm.org/D29001

Files:
  include/clang/Basic/DiagnosticCommonKinds.td
  lib/Frontend/CompilerInstance.cpp


Index: lib/Frontend/CompilerInstance.cpp
===
--- lib/Frontend/CompilerInstance.cpp
+++ lib/Frontend/CompilerInstance.cpp
@@ -1180,10 +1180,14 @@
 llvm::LockFileManager Locked(ModuleFileName);
 switch (Locked) {
 case llvm::LockFileManager::LFS_Error:
-  Diags.Report(ModuleNameLoc, diag::err_module_lock_failure)
+  // PCMCache takes care of correctness and locks are only necessary for
+  // performance. If there are errors creating the lock, do not use it
+  // and fallback to building the module ourselves.
+  Diags.Report(ModuleNameLoc, diag::remark_module_lock_failure)
   << Module->Name << Locked.getErrorMessage();
-  return false;
-
+  // Clear the lock file in case there's some leftover around.
+  Locked.unsafeRemoveLockFile();
+  // FALLTHROUGH
 case llvm::LockFileManager::LFS_Owned:
   // We're responsible for building the module ourselves.
   if (!compileModuleImpl(ImportingInstance, ModuleNameLoc, Module,
@@ -1203,11 +1207,14 @@
   case llvm::LockFileManager::Res_OwnerDied:
 continue; // try again to get the lock.
   case llvm::LockFileManager::Res_Timeout:
-Diags.Report(ModuleNameLoc, diag::err_module_lock_timeout)
+// Since PCMCache takes care of correctness, we try waiting for another
+// process to complete the build so that this isn't done twice. If we
+// reach a timeout, it's not a problem, try to build it ourselves then.
+Diags.Report(ModuleNameLoc, diag::remark_module_lock_timeout)
 << Module->Name;
 // Clear the lock file so that future invokations can make progress.
 Locked.unsafeRemoveLockFile();
-return false;
+continue;
   }
   break;
 }
Index: include/clang/Basic/DiagnosticCommonKinds.td
===
--- include/clang/Basic/DiagnosticCommonKinds.td
+++ include/clang/Basic/DiagnosticCommonKinds.td
@@ -88,10 +88,10 @@
   "module '%0' %select{is incompatible with|requires}1 feature '%2'">;
 def err_module_header_missing : Error<
   "%select{|umbrella }0header '%1' not found">;
-def err_module_lock_failure : Error<
-  "could not acquire lock file for module '%0': %1">, DefaultFatal;
-def err_module_lock_timeout : Error<
-  "timed out waiting to acquire lock file for module '%0'">, DefaultFatal;
+def remark_module_lock_failure : Remark<
+  "could not acquire lock file for module '%0': %1">, InGroup;
+def remark_module_lock_timeout : Remark<
+  "timed out waiting to acquire lock file for module '%0'">, 
InGroup;
 def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, 
   DefaultFatal;
 def err_module_prebuilt : Error<


Index: lib/Frontend/CompilerInstance.cpp
===
--- lib/Frontend/CompilerInstance.cpp
+++ lib/Frontend/CompilerInstance.cpp
@@ -1180,10 +1180,14 @@
 llvm::LockFileManager Locked(ModuleFileName);
 switch (Locked) {
 case llvm::LockFileManager::LFS_Error:
-  Diags.Report(ModuleNameLoc, diag::err_module_lock_failure)
+  // PCMCache takes care of correctness and locks are only necessary for
+  // performance. If there are errors creating the lock, do not use it
+  // and fallback to building the module ourselves.
+  Diags.Report(ModuleNameLoc, diag::remark_module_lock_failure)
   << Module->Name << Locked.getErrorMessage();
-  return false;
-
+  // Clear the lock file in case there's some leftover around.
+  Locked.unsafeRemoveLockFile();
+  // FALLTHROUGH
 case llvm::LockFileManager::LFS_Owned:
   // We're responsible for building the module ourselves.
   if (!compileModuleImpl(ImportingInstance, ModuleNameLoc, Module,
@@ -1203,11 +1207,14 @@
   case llvm::LockFileManager::Res_OwnerDied:
 continue; // try again to get the lock.
   case llvm::LockFileManager::Res_Timeout:
-Diags.Report(ModuleNameLoc, diag::err_module_lock_timeout)
+// Since PCMCache takes care of correctness, we try waiting for another
+// process to complete the build so that this isn't done twice. If we
+// reach a timeout, it's not a problem, try to build it ourselves then.
+Diags.Report(ModuleNameLoc, 

r292768 - DebugInfo: Omit class definitions even in the presence of available_externally vtables

2017-01-22 Thread David Blaikie via cfe-commits
Author: dblaikie
Date: Sun Jan 22 20:24:03 2017
New Revision: 292768

URL: http://llvm.org/viewvc/llvm-project?rev=292768=rev
Log:
DebugInfo: Omit class definitions even in the presence of available_externally 
vtables

To ensure optimization level doesn't pessimize the -fstandalone-debug
vtable debug info optimization (where class definitions are only emitted
where the vtable is emitted - reducing redundant debug info) ensure the
debug info class definition is still omitted when an
available_externally vtable definition is emitted for optimization
purposes.

Added:
cfe/trunk/test/CodeGenCXX/debug-info-class-optzns.cpp
Modified:
cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
cfe/trunk/lib/CodeGen/CGDebugInfo.h
cfe/trunk/lib/CodeGen/CGVTables.cpp

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.cpp?rev=292768=292767=292768=diff
==
--- cfe/trunk/lib/CodeGen/CGDebugInfo.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.cpp Sun Jan 22 20:24:03 2017
@@ -1714,7 +1714,26 @@ void CGDebugInfo::completeType(const Rec
 completeRequiredType(RD);
 }
 
+/// Return true if the class or any of its methods are marked dllimport.
+static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) {
+  if (RD->hasAttr())
+return true;
+  for (const CXXMethodDecl *MD : RD->methods())
+if (MD->hasAttr())
+  return true;
+  return false;
+}
+
 void CGDebugInfo::completeClassData(const RecordDecl *RD) {
+  if (auto *CXXRD = dyn_cast(RD))
+if (CGM.getVTableLinkage(CXXRD) ==
+llvm::GlobalValue::AvailableExternallyLinkage &&
+!isClassOrMethodDLLImport(CXXRD))
+  return;
+  completeClass(RD);
+}
+
+void CGDebugInfo::completeClass(const RecordDecl *RD) {
   if (DebugKind <= codegenoptions::DebugLineTablesOnly)
 return;
   QualType Ty = CGM.getContext().getRecordType(RD);
@@ -1760,16 +1779,6 @@ static bool isDefinedInClangModule(const
   return true;
 }
 
-/// Return true if the class or any of its methods are marked dllimport.
-static bool isClassOrMethodDLLImport(const CXXRecordDecl *RD) {
-  if (RD->hasAttr())
-return true;
-  for (const CXXMethodDecl *MD : RD->methods())
-if (MD->hasAttr())
-  return true;
-  return false;
-}
-
 static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
  bool DebugTypeExtRefs, const RecordDecl *RD,
  const LangOptions ) {

Modified: cfe/trunk/lib/CodeGen/CGDebugInfo.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDebugInfo.h?rev=292768=292767=292768=diff
==
--- cfe/trunk/lib/CodeGen/CGDebugInfo.h (original)
+++ cfe/trunk/lib/CodeGen/CGDebugInfo.h Sun Jan 22 20:24:03 2017
@@ -409,6 +409,7 @@ public:
   void completeType(const RecordDecl *RD);
   void completeRequiredType(const RecordDecl *RD);
   void completeClassData(const RecordDecl *RD);
+  void completeClass(const RecordDecl *RD);
 
   void completeTemplateDefinition(const ClassTemplateSpecializationDecl );
 

Modified: cfe/trunk/lib/CodeGen/CGVTables.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGVTables.cpp?rev=292768=292767=292768=diff
==
--- cfe/trunk/lib/CodeGen/CGVTables.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGVTables.cpp Sun Jan 22 20:24:03 2017
@@ -744,9 +744,10 @@ CodeGenModule::getVTableLinkage(const CX
 switch (keyFunction->getTemplateSpecializationKind()) {
   case TSK_Undeclared:
   case TSK_ExplicitSpecialization:
-assert((def || CodeGenOpts.OptimizationLevel > 0) &&
-   "Shouldn't query vtable linkage without key function or "
-   "optimizations");
+assert((def || CodeGenOpts.OptimizationLevel > 0 ||
+CodeGenOpts.getDebugInfo() != codegenoptions::NoDebugInfo) &&
+   "Shouldn't query vtable linkage without key function, "
+   "optimizations, or debug info");
 if (!def && CodeGenOpts.OptimizationLevel > 0)
   return llvm::GlobalVariable::AvailableExternallyLinkage;
 

Added: cfe/trunk/test/CodeGenCXX/debug-info-class-optzns.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/debug-info-class-optzns.cpp?rev=292768=auto
==
--- cfe/trunk/test/CodeGenCXX/debug-info-class-optzns.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/debug-info-class-optzns.cpp Sun Jan 22 20:24:03 
2017
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -triple x86_64-unknown_unknown -emit-llvm 
-debug-info-kind=limited %s -O1 -o - | FileCheck %s
+
+// Ensure class definitions are not emitted to debug info just because the
+// vtable is emitted for optimization purposes (as 

[PATCH] D28973: Supresses misc-move-constructor-init warning for const fields.

2017-01-22 Thread Alexander Kornienko via Phabricator via cfe-commits
alexfh requested changes to this revision.
alexfh added inline comments.
This revision now requires changes to proceed.



Comment at: clang-tools-extra/test/clang-tidy/misc-move-constructor-init.cpp:88
+struct O {
+  O(O&& other) : b(other.b) {} // ok
+  const B b;

The test is fine, but it would also pass, if the check verified constness of 
the field being initialized. I'd suggest adding another one that shows a 
const-qualified initializer used to initialize a non-const field.



Comment at: clang-tools-extra/test/clang-tidy/misc-move-constructor-init.cpp:90
+  const B b;
+}
+

Missing semicolon. I wonder how the test still passes. It passes, doesn't it?


https://reviews.llvm.org/D28973



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


[PATCH] D28952: [analyzer] Add new Z3 constraint manager backend

2017-01-22 Thread Nuno Lopes via Phabricator via cfe-commits
nlopes added a comment.

Cool work Dominic!
Just a few random comments from the peanut gallery regarding the usage of Z3:

- I would definitely split the Z3Expr into expr/solver/model classes. Several 
advantages: plugging in new solvers becomes easier and reference counting can 
be handled more safely and automatically. Right now your solver+model related 
code handled ref-counting "by hand", which can easily lead to bugs.
- I would add an rvalue constructor to the expr class to avoid ref-counting 
when unneeded.
- Function z3Expr::fromData() seems to be able to create arbitrarily-sized 
bit-vectors.  I would limit to e.g. 512 bits or something like that.  Z3 is 
super slow with huge bit-vectors. If you feel fancy (for a following version of 
this feature), you could encode this information lazily (based on the model).
- Z3Expr::fromInt() -- why take a string as input and not a uin64_t?
- Why call simplify before asserting a constraint?  That's usually a pretty 
slow thing to do (in my experience).
- You should replace Z3_mk_solver() with something fancier.  If you don't feel 
fancy, just use Z3_mk_simple_solver()  (simple is short for simplifying btw).  
If you know the theory of the constraints (e.g., without floats, it would be 
QF_BV), you should use Z3_mk_solver_for_theory()  (or whatever the name was).  
If you feel really fancy, you could roll your own tactic (in my tools I often 
have a tactic class to build my own tactics; Z3 even allows you to case split 
on the theory after simplifications)
- Instead of asserting multiple constraints to the solver, I would and() them 
and assert just once (plays nicer with some preprocessors of Z3)
- Timeout: SMT solvers sometimes go crazy and take forever.  I would advise to 
add a timeout to the solver to avoid getting caught on a trap.  This timeout 
can be different for the two use cases: check if a path is feasible (lower 
timeout), or check if you actually have a bug (higher timeout)
- Also, I didn't see anything regarding memory (I might have missed yet).  Are 
you using the array theory?  If so, I would probably advise benchmarking it 
carefully since Z3's support for arrays is not great (even though it has 
improved a bit in the last year or so).

BTW, adding small amount of constant folding in the expression builder is 
usually good, since you save time in Z3 preprocessor. Especially if you want to 
go for smallish timeouts (likely).  If you want to be fancy, you can also 
canonicalize expressions like Z3 likes (e.g., only ule/sle, no slt, sgt, etc).


https://reviews.llvm.org/D28952



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


[PATCH] D20693: [clang-tidy] New checker to replace dynamic exception specifications

2017-01-22 Thread don hinton via Phabricator via cfe-commits
hintonda updated this revision to Diff 85291.
hintonda added a comment.

- Rebased.


https://reviews.llvm.org/D20693

Files:
  clang-tidy/modernize/CMakeLists.txt
  clang-tidy/modernize/ModernizeTidyModule.cpp
  clang-tidy/modernize/UseNoexceptCheck.cpp
  clang-tidy/modernize/UseNoexceptCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/modernize-use-noexcept.rst
  test/clang-tidy/modernize-use-noexcept-macro.cpp
  test/clang-tidy/modernize-use-noexcept-opt.cpp
  test/clang-tidy/modernize-use-noexcept.cpp

Index: test/clang-tidy/modernize-use-noexcept.cpp
===
--- /dev/null
+++ test/clang-tidy/modernize-use-noexcept.cpp
@@ -0,0 +1,87 @@
+// RUN: %check_clang_tidy %s modernize-use-noexcept %t -- \
+// RUN:   -- -std=c++11
+
+class A {};
+class B {};
+
+void foo() throw();
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foo() noexcept;
+
+void bar() throw(...);
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: dynamic exception specification 'throw(...)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void bar() noexcept(false);
+
+void k() throw(int(int));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int))' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void k() noexcept(false);
+
+void foobar() throw(A, B)
+{}
+// CHECK-MESSAGES: :[[@LINE-2]]:15: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void foobar() noexcept(false)
+
+void baz(int = (throw A(), 0)) throw(A, B) {}
+// CHECK-MESSAGES: :[[@LINE-1]]:32: warning: dynamic exception specification 'throw(A, B)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void baz(int = (throw A(), 0)) noexcept(false) {}
+
+void g(void (*fp)(void) throw());
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: void g(void (*fp)(void) noexcept);
+
+void f(void (*fp)(void) throw(int)) throw(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'throw(char)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void f(void (*fp)(void) noexcept(false)) noexcept(false);
+
+#define THROW throw
+void h(void (*fp)(void) THROW(int)) THROW(char);
+// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: dynamic exception specification 'THROW(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:37: warning: dynamic exception specification 'THROW(char)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void h(void (*fp)(void) noexcept(false)) noexcept(false);
+
+void j() throw(int(int) throw(void(void) throw(int)));
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: dynamic exception specification 'throw(int(int) throw(void(void) throw(int)))' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void j() noexcept(false);
+
+class Y {
+  Y() throw() = default;
+};
+// CHECK-MESSAGES: :[[@LINE-2]]:7: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-FIXES: Y() noexcept = default;
+
+struct Z {
+  void operator delete(void *ptr) throw();
+  void operator delete[](void *ptr) throw(int);
+  ~Z() throw(int) {}
+};
+// CHECK-MESSAGES: :[[@LINE-4]]:35: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:37: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-4]]:8: warning: dynamic exception specification 'throw(int)' is deprecated; consider using 'noexcept(false)' instead [modernize-use-noexcept]
+// CHECK-FIXES: void operator delete(void *ptr) noexcept;
+// CHECK-FIXES: void operator delete[](void *ptr) noexcept(false);
+// CHECK-FIXES: ~Z() noexcept(false) {}
+
+struct S {
+  void f() throw();
+};
+void f(void (S::*)() throw());
+// CHECK-MESSAGES: :[[@LINE-3]]:12: warning: dynamic exception specification 'throw()' is deprecated; consider using 'noexcept' instead [modernize-use-noexcept]
+// CHECK-MESSAGES: :[[@LINE-2]]:22: warning: dynamic exception 

[PATCH] D28520: Disable -Wthread-safety-analysis for some functions in __thread_support

2017-01-22 Thread Dimitry Andric via Phabricator via cfe-commits
dim updated this revision to Diff 85283.
dim added a comment.

Let's try it with this much simpler version instead, which disables the thread 
safety analysis _only_ for FreeBSD, and nowhere else.  And no messing with 
capabilities, either.


https://reviews.llvm.org/D28520

Files:
  include/__threading_support


Index: include/__threading_support
===
--- include/__threading_support
+++ include/__threading_support
@@ -40,6 +40,12 @@
 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
 #endif
 
+#if defined(__FreeBSD__) && defined(__clang__) && 
__has_attribute(no_thread_safety_analysis)
+#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS 
__attribute__((no_thread_safety_analysis))
+#else
+#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
+#endif
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
@@ -102,25 +108,25 @@
 _LIBCPP_THREAD_ABI_VISIBILITY
 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
 
 _LIBCPP_THREAD_ABI_VISIBILITY
 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
 
 _LIBCPP_THREAD_ABI_VISIBILITY
@@ -133,10 +139,10 @@
 _LIBCPP_THREAD_ABI_VISIBILITY
 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
timespec *__ts);
 


Index: include/__threading_support
===
--- include/__threading_support
+++ include/__threading_support
@@ -40,6 +40,12 @@
 #define _LIBCPP_THREAD_ABI_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
 #endif
 
+#if defined(__FreeBSD__) && defined(__clang__) && __has_attribute(no_thread_safety_analysis)
+#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS __attribute__((no_thread_safety_analysis))
+#else
+#define _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
+#endif
+
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if defined(_LIBCPP_HAS_THREAD_API_PTHREAD)
@@ -102,25 +108,25 @@
 _LIBCPP_THREAD_ABI_VISIBILITY
 int __libcpp_recursive_mutex_init(__libcpp_recursive_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_recursive_mutex_lock(__libcpp_recursive_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 bool __libcpp_recursive_mutex_trylock(__libcpp_recursive_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_recursive_mutex_unlock(__libcpp_recursive_mutex_t *__m);
 
 _LIBCPP_THREAD_ABI_VISIBILITY
 int __libcpp_recursive_mutex_destroy(__libcpp_recursive_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_mutex_lock(__libcpp_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 bool __libcpp_mutex_trylock(__libcpp_mutex_t *__m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_mutex_unlock(__libcpp_mutex_t *__m);
 
 _LIBCPP_THREAD_ABI_VISIBILITY
@@ -133,10 +139,10 @@
 _LIBCPP_THREAD_ABI_VISIBILITY
 int __libcpp_condvar_broadcast(__libcpp_condvar_t* __cv);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_condvar_wait(__libcpp_condvar_t* __cv, __libcpp_mutex_t* __m);
 
-_LIBCPP_THREAD_ABI_VISIBILITY
+_LIBCPP_THREAD_ABI_VISIBILITY _LIBCPP_NO_THREAD_SAFETY_ANALYSIS
 int __libcpp_condvar_timedwait(__libcpp_condvar_t *__cv, __libcpp_mutex_t *__m,
timespec *__ts);
 
___

[PATCH] D28983: clang-format: remove tests that assume no config file will be found as this is not always the case

2017-01-22 Thread Eric Liu via Phabricator via cfe-commits
ioeric accepted this revision.
ioeric added a comment.
This revision is now accepted and ready to land.

Lgtm


https://reviews.llvm.org/D28983



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


Re: r292558 - Add documentation for constexpr string builtin support.

2017-01-22 Thread Kim Gräsman via cfe-commits
Hi Richard,

On Fri, Jan 20, 2017 at 1:58 AM, Richard Smith via cfe-commits
 wrote:
>
> +String builtins
> +---
> +
> +Clang provides constant expression evaluation support for builtins forms of
> +the following functions from the C standard library  header:
> +
> +* ``memchr``
> +* ``memcmp``
> +* ``strchr``

This should say , right?

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


Re: r291905 - [Sema] Add warning for unused lambda captures

2017-01-22 Thread Malcolm Parsons via cfe-commits
On 20 January 2017 at 21:32, Nico Weber  wrote:
> This warns about code like
>
>   constexpr int foo = 4;
>   []() { use(foo); }
>
> That's correct, but removing  then makes MSVC complain about this code
> like "error C3493: 'foo' cannot be implicitly captured because no default
> capture mode has been specified". A workaround is to make foo static const
> instead of constexpr.
>
> This seems like an MSVC bug, but it's still a bit annoying that clang now
> suggests doing things that won't build in other compilers. Any ideas what to
> do about this?

Should Clang care about the behaviour of other compilers that don't
follow the standard?

You could:
Disable the warning on the command line.
Disable the warning with a pragma.
Cast foo to void inside the lambda.
Only capture foo when building with MSVC.
Stop building with MSVC.
Complain to Microsoft.

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


[PATCH] D28520: Disable -Wthread-safety-analysis for some functions in __thread_support

2017-01-22 Thread Dimitry Andric via Phabricator via cfe-commits
dim added a comment.

In https://reviews.llvm.org/D28520#648880, @delesley wrote:

> Sorry about the slow response.   My main concern here is that the thread 
> safety analysis was designed for use with a library that wraps the system 
> mutex in a separate Mutex class.  We did that specifically to avoid breaking 
> anything; code has to opt-in to the static checking by defining and using a 
> Mutex class, and the API of that class is restricted to calls that can be 
> easily checked via annotations.  Including attributes directly in the 
> standard library has the potential to cause lots of breakage and false 
> positives.


Yes, I agree with that.  However, on FreeBSD the pthread functions themselves 
are already annotated, so the libc++ wrapper functions cause -Werror warnings 
during the tests.  Therefore one of my suggestions was to explicitly turn off 
warnings using `no_thread_safety_analysis` attributes.  Is there any 
disadvantage in doing that?

> Is there some way to control the #ifdefs so that the annotations are turned 
> off by default for everyone except possibly freebsd, but there's still a way 
> to turn them on for users who want to see the warnings?  I'm not a libcxx 
> expert.

Yes, that was one of my other suggestions, using `#if defined(__FreeBSD__)` to 
limit these attributes to FreeBSD only.   We can do that either with the 
`no_thread_safety_analysis` attributes, or with the 'real' annotations, though 
the latter are not really useful in this case.

I'm really open to any variant, as long as something that works can get in 
before the 4.0.0 release. :)


https://reviews.llvm.org/D28520



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