[PATCH] D27800: Add overload of TransformToPotentiallyEvaluated for TypeSourceInfo
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.
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.
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
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
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
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
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
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
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
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
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.
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
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
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
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
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.
Hi Richard, On Fri, Jan 20, 2017 at 1:58 AM, Richard Smith via cfe-commitswrote: > > +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
On 20 January 2017 at 21:32, Nico Weberwrote: > 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
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