r337125 - Run thread safety tests with both lock and capability attributes; NFC to the analysis behavior.
Author: aaronballman Date: Sun Jul 15 05:08:52 2018 New Revision: 337125 URL: http://llvm.org/viewvc/llvm-project?rev=337125&view=rev Log: Run thread safety tests with both lock and capability attributes; NFC to the analysis behavior. Patch thanks to Aaron Puchert. Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Modified: cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp?rev=337125&r1=337124&r2=337125&view=diff == --- cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp (original) +++ cfe/trunk/test/SemaCXX/warn-thread-safety-analysis.cpp Sun Jul 15 05:08:52 2018 @@ -1,12 +1,11 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=0 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=1 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=0 %s -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_ASSERT_CAPABILITY=1 -DUSE_TRY_ACQUIRE_CAPABILITY %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=0 %s +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wthread-safety -Wthread-safety-beta -Wno-thread-safety-negative -fcxx-exceptions -DUSE_CAPABILITY=1 %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety -std=c++11 -Wc++98-compat %s // FIXME: should also run %clang_cc1 -fsyntax-only -verify -Wthread-safety %s -#define LOCKABLE __attribute__((lockable)) #define SCOPED_LOCKABLE __attribute__((scoped_lockable)) #define GUARDED_BY(x)__attribute__((guarded_by(x))) #define GUARDED_VAR __attribute__((guarded_var)) @@ -14,42 +13,46 @@ #define PT_GUARDED_VAR __attribute__((pt_guarded_var)) #define ACQUIRED_AFTER(...) __attribute__((acquired_after(__VA_ARGS__))) #define ACQUIRED_BEFORE(...) __attribute__((acquired_before(__VA_ARGS__))) -#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) -#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) -#if USE_ASSERT_CAPABILITY +#if USE_CAPABILITY +#define LOCKABLE__attribute__((capability("mutex"))) #define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_capability(__VA_ARGS__))) #define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_capability(__VA_ARGS__))) -#else -#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__))) -#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__))) -#endif - -#ifdef USE_TRY_ACQUIRE_CAPABILITY +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((acquire_capability(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__))) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__))) #define SHARED_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) +#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) +#define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__))) +#define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__))) #else +#define LOCKABLE__attribute__((lockable)) +#define ASSERT_EXCLUSIVE_LOCK(...) __attribute__((assert_exclusive_lock(__VA_ARGS__))) +#define ASSERT_SHARED_LOCK(...) __attribute__((assert_shared_lock(__VA_ARGS__))) +#define EXCLUSIVE_LOCK_FUNCTION(...) __attribute__((exclusive_lock_function(__VA_ARGS__))) +#define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__))) #define SHARED_TRYLOCK_FUNCTION(...) __attribute__((shared_trylock_function(__VA_ARGS__))) +#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((unlock
[PATCH] D49275: Thread safety: Run tests with both lock and capability attributes
aaron.ballman closed this revision. aaron.ballman added a comment. In https://reviews.llvm.org/D49275#1162204, @aaronpuchert wrote: > Thanks for the review. Could you commit this for me (`Aaron Puchert > `)? Happy to do so. I've commit in r337125. Thank you for the patch! Repository: rC Clang https://reviews.llvm.org/D49275 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D48845: [Sema] Add fixit for unused lambda captures
aaron.ballman accepted this revision. aaron.ballman added a comment. Aside from a small nit in the comments, LGTM. Comment at: include/clang/Sema/Sema.h:5608 + /// diagnostic is emitted. + bool DiagnoseUnusedLambdaCapture(const SourceRange CaptureRange, + const sema::Capture &From); No need to mark the SourceRange const, unless you intended to pass it by reference. Repository: rC Clang https://reviews.llvm.org/D48845 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49348: Harden/relax clang/test/CodeGen/opt-record-MIR.c test
lebedev.ri created this revision. lebedev.ri added reviewers: anemet, aaron.ballman, hfinkel. Herald added a subscriber: cfe-commits. If the build path is short, `Line` field can end up fitting on the same line as `File`, but the `{{.*}}` would consume it. Keeping in mind https://reviews.llvm.org/rL293149, i think we can fix it, while keeping it working when there are and there are not any quotations. At least this fixes this test for me. Repository: rC Clang https://reviews.llvm.org/D49348 Files: test/CodeGen/opt-record-MIR.c Index: test/CodeGen/opt-record-MIR.c === --- test/CodeGen/opt-record-MIR.c +++ test/CodeGen/opt-record-MIR.c @@ -21,8 +21,9 @@ // YAML: --- !Missed // YAML: Pass:regalloc // YAML: Name:LoopSpillReload -// YAML: DebugLoc:{ File: {{.*}}, -// YAML:Line: 10, Column: 11 } +// YAML: DebugLoc:{ File: {{.*}}.c{{['"]*}}, +// YAML:Line: 10, +// YAML:Column: 11 } // YAML: Function:foo // YAML: Args: // YAML: - NumSpills: '{{.}}' Index: test/CodeGen/opt-record-MIR.c === --- test/CodeGen/opt-record-MIR.c +++ test/CodeGen/opt-record-MIR.c @@ -21,8 +21,9 @@ // YAML: --- !Missed // YAML: Pass:regalloc // YAML: Name:LoopSpillReload -// YAML: DebugLoc:{ File: {{.*}}, -// YAML:Line: 10, Column: 11 } +// YAML: DebugLoc:{ File: {{.*}}.c{{['"]*}}, +// YAML:Line: 10, +// YAML:Column: 11 } // YAML: Function:foo // YAML: Args: // YAML: - NumSpills: '{{.}}' ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49348: Harden/relax clang/test/CodeGen/opt-record-MIR.c test
lebedev.ri updated this revision to Diff 155591. lebedev.ri added a comment. Simplify regex even more. Repository: rC Clang https://reviews.llvm.org/D49348 Files: test/CodeGen/opt-record-MIR.c Index: test/CodeGen/opt-record-MIR.c === --- test/CodeGen/opt-record-MIR.c +++ test/CodeGen/opt-record-MIR.c @@ -21,8 +21,9 @@ // YAML: --- !Missed // YAML: Pass:regalloc // YAML: Name:LoopSpillReload -// YAML: DebugLoc:{ File: {{.*}}, -// YAML:Line: 10, Column: 11 } +// YAML: DebugLoc:{ File: {{[^,]+}}, +// YAML:Line: 10, +// YAML:Column: 11 } // YAML: Function:foo // YAML: Args: // YAML: - NumSpills: '{{.}}' Index: test/CodeGen/opt-record-MIR.c === --- test/CodeGen/opt-record-MIR.c +++ test/CodeGen/opt-record-MIR.c @@ -21,8 +21,9 @@ // YAML: --- !Missed // YAML: Pass:regalloc // YAML: Name:LoopSpillReload -// YAML: DebugLoc:{ File: {{.*}}, -// YAML:Line: 10, Column: 11 } +// YAML: DebugLoc:{ File: {{[^,]+}}, +// YAML:Line: 10, +// YAML:Column: 11 } // YAML: Function:foo // YAML: Args: // YAML: - NumSpills: '{{.}}' ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49354: [MinGW] Automatically mangle Windows-specific entry points as C
mstorsjo created this revision. mstorsjo added reviewers: majnemer, zturner, pcc, rnk, hans, compnerd, smeenai. This mangles entry points wmain, WinMain, wWinMain or DllMain as C functions, to match the ABI for these functions. We already did the same for these functions in MSVC mode, but we also should do the same in the Itanium ABI. This fixes PR38124. Repository: rC Clang https://reviews.llvm.org/D49354 Files: lib/AST/ItaniumMangle.cpp test/CodeGenCXX/mangle-mingw.cpp Index: test/CodeGenCXX/mangle-mingw.cpp === --- /dev/null +++ test/CodeGenCXX/mangle-mingw.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-w64-mingw32 | FileCheck %s + +int func() { return 0; } +// CHECK-DAG: @_Z4funcv + +int main() { return 0; } +// CHECK-DAG: @main + +int wmain() { return 0; } +// CHECK-DAG: @wmain + +int WinMain() { return 0; } +// CHECK-DAG: @WinMain + +int wWinMain() { return 0; } +// CHECK-DAG: @wWinMain + +int DllMain() { return 0; } +// CHECK-DAG: @DllMain Index: lib/AST/ItaniumMangle.cpp === --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -590,6 +590,18 @@ if (FD->isMain()) return false; +// The Windows ABI expects that we would never mangle "typical" +// user-defined entry points regardless of visibility or freestanding-ness. +// +// N.B. This is distinct from asking about "main". "main" has a lot of +// special rules associated with it in the standard while these +// user-defined entry points are outside of the purview of the standard. +// For example, there can be only one definition for "main" in a standards +// compliant program; however nothing forbids the existence of wmain and +// WinMain in the same translation unit. +if (FD->isMSVCRTEntryPoint()) + return false; + // C++ functions and those whose names are not a simple identifier need // mangling. if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage) Index: test/CodeGenCXX/mangle-mingw.cpp === --- /dev/null +++ test/CodeGenCXX/mangle-mingw.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-w64-mingw32 | FileCheck %s + +int func() { return 0; } +// CHECK-DAG: @_Z4funcv + +int main() { return 0; } +// CHECK-DAG: @main + +int wmain() { return 0; } +// CHECK-DAG: @wmain + +int WinMain() { return 0; } +// CHECK-DAG: @WinMain + +int wWinMain() { return 0; } +// CHECK-DAG: @wWinMain + +int DllMain() { return 0; } +// CHECK-DAG: @DllMain Index: lib/AST/ItaniumMangle.cpp === --- lib/AST/ItaniumMangle.cpp +++ lib/AST/ItaniumMangle.cpp @@ -590,6 +590,18 @@ if (FD->isMain()) return false; +// The Windows ABI expects that we would never mangle "typical" +// user-defined entry points regardless of visibility or freestanding-ness. +// +// N.B. This is distinct from asking about "main". "main" has a lot of +// special rules associated with it in the standard while these +// user-defined entry points are outside of the purview of the standard. +// For example, there can be only one definition for "main" in a standards +// compliant program; however nothing forbids the existence of wmain and +// WinMain in the same translation unit. +if (FD->isMSVCRTEntryPoint()) + return false; + // C++ functions and those whose names are not a simple identifier need // mangling. if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage) ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49355: Thread safety analysis: Allow lock upgrading and downgrading
aaronpuchert created this revision. aaronpuchert added reviewers: aaron.ballman, delesley. Herald added a subscriber: cfe-commits. We can now have methods that release a locked in shared mode and acquire it in exclusive mode or the other way around. The fix was just to release the locks before acquiring them. Also added a few test cases for non-generic unlock methods and removed an unnecessary const_cast. Repository: rC Clang https://reviews.llvm.org/D49355 Files: lib/Analysis/ThreadSafety.cpp test/SemaCXX/warn-thread-safety-analysis.cpp Index: test/SemaCXX/warn-thread-safety-analysis.cpp === --- test/SemaCXX/warn-thread-safety-analysis.cpp +++ test/SemaCXX/warn-thread-safety-analysis.cpp @@ -22,8 +22,6 @@ #define SHARED_LOCK_FUNCTION(...) __attribute__((acquire_shared_capability(__VA_ARGS__))) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((try_acquire_capability(__VA_ARGS__))) #define SHARED_TRYLOCK_FUNCTION(...)__attribute__((try_acquire_shared_capability(__VA_ARGS__))) -#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) -#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) #define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((requires_capability(__VA_ARGS__))) #define SHARED_LOCKS_REQUIRED(...) __attribute__((requires_shared_capability(__VA_ARGS__))) #else @@ -34,11 +32,11 @@ #define SHARED_LOCK_FUNCTION(...) __attribute__((shared_lock_function(__VA_ARGS__))) #define EXCLUSIVE_TRYLOCK_FUNCTION(...) __attribute__((exclusive_trylock_function(__VA_ARGS__))) #define SHARED_TRYLOCK_FUNCTION(...)__attribute__((shared_trylock_function(__VA_ARGS__))) -#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) -#define SHARED_UNLOCK_FUNCTION(...) __attribute__((unlock_function(__VA_ARGS__))) #define EXCLUSIVE_LOCKS_REQUIRED(...) __attribute__((exclusive_locks_required(__VA_ARGS__))) #define SHARED_LOCKS_REQUIRED(...) __attribute__((shared_locks_required(__VA_ARGS__))) #endif +#define EXCLUSIVE_UNLOCK_FUNCTION(...) __attribute__((release_capability(__VA_ARGS__))) +#define SHARED_UNLOCK_FUNCTION(...) __attribute__((release_shared_capability(__VA_ARGS__))) #define UNLOCK_FUNCTION(...)__attribute__((unlock_function(__VA_ARGS__))) #define LOCK_RETURNED(x)__attribute__((lock_returned(x))) #define LOCKS_EXCLUDED(...) __attribute__((locks_excluded(__VA_ARGS__))) @@ -50,10 +48,15 @@ void Lock() EXCLUSIVE_LOCK_FUNCTION(); void ReaderLock() SHARED_LOCK_FUNCTION(); void Unlock() UNLOCK_FUNCTION(); + void ExclusiveUnlock() EXCLUSIVE_UNLOCK_FUNCTION(); + void ReaderUnlock() SHARED_UNLOCK_FUNCTION(); bool TryLock() EXCLUSIVE_TRYLOCK_FUNCTION(true); bool ReaderTryLock() SHARED_TRYLOCK_FUNCTION(true); void LockWhen(const int &cond) EXCLUSIVE_LOCK_FUNCTION(); + void PromoteShared() SHARED_UNLOCK_FUNCTION() EXCLUSIVE_LOCK_FUNCTION(); + void DemoteExclusive() EXCLUSIVE_UNLOCK_FUNCTION() SHARED_LOCK_FUNCTION(); + // for negative capabilities const Mutex& operator!() const { return *this; } @@ -704,6 +707,26 @@ sls_mu.Unlock(); } +void shared_fun_9() { + sls_mu.Lock(); + sls_mu.ExclusiveUnlock(); + + sls_mu.ReaderLock(); + sls_mu.ReaderUnlock(); +} + +void shared_fun_10() { + sls_mu.Lock(); + sls_mu.DemoteExclusive(); + sls_mu.ReaderUnlock(); +} + +void shared_fun_11() { + sls_mu.ReaderLock(); + sls_mu.PromoteShared(); + sls_mu.Unlock(); +} + void shared_bad_0() { sls_mu.Lock(); // \ // expected-warning {{mutex 'sls_mu' is acquired exclusively and shared in the same scope}} @@ -737,6 +760,32 @@ sls_mu.Unlock(); } +void shared_bad_3() { + sls_mu.Lock(); + sls_mu.ReaderUnlock(); // \ +// expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}} +} + +void shared_bad_4() { + sls_mu.ReaderLock(); + sls_mu.ExclusiveUnlock(); // \ +// expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}} +} + +void shared_bad_5() { + sls_mu.Lock(); + sls_mu.PromoteShared(); // \ +// expected-warning {{releasing mutex 'sls_mu' using shared access, expected exclusive access}} + sls_mu.ExclusiveUnlock(); +} + +void shared_bad_6() { + sls_mu.ReaderLock(); + sls_mu.DemoteExclusive(); // \ +// expected-warning {{releasing mutex 'sls_mu' using exclusive access, expected shared access}} + sls_mu.ReaderUnlock(); +} + // FIXME: Add support for functions (not only methods) class LRBar { public: Index: lib/Analysis/ThreadSafety.cpp === --- lib/Analysis/ThreadSafety.cpp +++ lib/Analysis/ThreadSafety.cpp @@ -109,9 +109,7 @@ /// along with additional information, such as where it was acquired, whether /// it is exclusive or shared, etc. /// -/// FIXME: thi
[PATCH] D49356: [clang-tidy: modernize] Fix modernize-use-equals-default with {} brackets list initialization: patch
IdrissRio created this revision. IdrissRio added reviewers: aaron.ballman, hokein, alexfh. Herald added a subscriber: cfe-commits. Hello, i would like to suggest a fix for one of the checks in clang-tidy. The bug was reported in https://bugs.llvm.org/show_bug.cgi?id=38039 where you can find more information Repository: rCTE Clang Tools Extra https://reviews.llvm.org/D49356 Files: clang-tidy/modernize/UseEqualsDefaultCheck.cpp test/clang-tidy/modernize-use-equals-default-copy.cpp Index: test/clang-tidy/modernize-use-equals-default-copy.cpp === --- test/clang-tidy/modernize-use-equals-default-copy.cpp +++ test/clang-tidy/modernize-use-equals-default-copy.cpp @@ -497,3 +497,11 @@ STRUCT_WITH_COPY_ASSIGN(unsigned char, Hex8CopyAssign) // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy-assignment operator // CHECK-MESSAGES: :[[@LINE-9]]:40: note: + +// Use of braces +struct UOB{ + UOB(const UOB &Other):j{Other.j}{} + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default] + // CHECK-FIXES: UOB(const UOB &Other)= default; + int j; +}; Index: clang-tidy/modernize/UseEqualsDefaultCheck.cpp === --- clang-tidy/modernize/UseEqualsDefaultCheck.cpp +++ clang-tidy/modernize/UseEqualsDefaultCheck.cpp @@ -97,6 +97,7 @@ isMemberInitializer(), forField(equalsNode(Field)), withInitializer(anyOf( AccessToFieldInParam, + initListExpr(has(AccessToFieldInParam)), cxxConstructExpr(allOf( hasDeclaration(cxxConstructorDecl(isCopyConstructor())), argumentCountIs(1), Index: test/clang-tidy/modernize-use-equals-default-copy.cpp === --- test/clang-tidy/modernize-use-equals-default-copy.cpp +++ test/clang-tidy/modernize-use-equals-default-copy.cpp @@ -497,3 +497,11 @@ STRUCT_WITH_COPY_ASSIGN(unsigned char, Hex8CopyAssign) // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: use '= default' to define a trivial copy-assignment operator // CHECK-MESSAGES: :[[@LINE-9]]:40: note: + +// Use of braces +struct UOB{ + UOB(const UOB &Other):j{Other.j}{} + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use '= default' to define a trivial copy constructor [modernize-use-equals-default] + // CHECK-FIXES: UOB(const UOB &Other)= default; + int j; +}; Index: clang-tidy/modernize/UseEqualsDefaultCheck.cpp === --- clang-tidy/modernize/UseEqualsDefaultCheck.cpp +++ clang-tidy/modernize/UseEqualsDefaultCheck.cpp @@ -97,6 +97,7 @@ isMemberInitializer(), forField(equalsNode(Field)), withInitializer(anyOf( AccessToFieldInParam, + initListExpr(has(AccessToFieldInParam)), cxxConstructExpr(allOf( hasDeclaration(cxxConstructorDecl(isCopyConstructor())), argumentCountIs(1), ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49354: [MinGW] Automatically mangle Windows-specific entry points as C
majnemer accepted this revision. majnemer added a comment. This revision is now accepted and ready to land. LGTM Repository: rC Clang https://reviews.llvm.org/D49354 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49360: [analyzer] Add support for more basic_string API in DanglingInternalBufferChecker
rnkovacs created this revision. rnkovacs added reviewers: NoQ, xazax.hun, george.karpenkov. Herald added subscribers: mikhail.ramalho, a.sidorin, dkrupp, szepet, baloghadamsoftware, whisperity. A pointer referring to the elements of a `basic_string` may be invalidated by calling a non-const member function, except `operator[]`, `at`, `front`, `back`, `begin`, `rbegin`, `end`, and `rend`. The checker now warns if the pointer is used after such operations. FIXME: warning messages. Repository: rC Clang https://reviews.llvm.org/D49360 Files: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp test/Analysis/dangling-internal-buffer.cpp Index: test/Analysis/dangling-internal-buffer.cpp === --- test/Analysis/dangling-internal-buffer.cpp +++ test/Analysis/dangling-internal-buffer.cpp @@ -2,13 +2,35 @@ namespace std { -template< typename CharT > +typedef int size_type; + +template class basic_string { public: + basic_string(); + basic_string(const CharT *s); + ~basic_string(); + void clear(); + + basic_string &operator=(const basic_string &str); + basic_string &operator+=(const basic_string &str); + const CharT *c_str() const; const CharT *data() const; CharT *data(); + + basic_string &append(size_type count, CharT ch); + basic_string &assign(size_type count, CharT ch); + basic_string &erase(size_type index, size_type count); + basic_string &insert(size_type index, size_type count, CharT ch); + basic_string &replace(size_type pos, size_type count, const basic_string &str); + void pop_back(); + void push_back(CharT ch); + void reserve(size_type new_cap); + void resize(size_type count); + void shrink_to_fit(); + void swap(basic_string &other); }; typedef basic_string string; @@ -23,73 +45,70 @@ void consume(const char16_t *) {} void consume(const char32_t *) {} -void deref_after_scope_char_cstr() { - const char *c; +void deref_after_scope_char(bool cond) { + const char *c, *d; { std::string s; c = s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} +d = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} + }// expected-note {{Internal buffer is released because the object was destroyed}} + // expected-note@-1 {{Internal buffer is released because the object was destroyed}} std::string s; const char *c2 = s.c_str(); - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} -} - -void deref_after_scope_char_data() { - const char *c; - { -std::string s; -c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} - std::string s; - const char *c2 = s.data(); - consume(c); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} + if (cond) { +// expected-note@-1 {{Assuming 'cond' is not equal to 0}} +// expected-note@-2 {{Taking true branch}} +// expected-note@-3 {{Assuming 'cond' is 0}} +// expected-note@-4 {{Taking false branch}} +consume(c); // expected-warning {{Use of memory after it is freed}} +// expected-note@-1 {{Use of memory after it is freed}} + } else { +consume(d); // expected-warning {{Use of memory after it is freed}} +// expected-note@-1 {{Use of memory after it is freed}} + } } void deref_after_scope_char_data_non_const() { char *c; { std::string s; c = s.data(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} + } // expected-note {{Internal buffer is released because the object was destroyed}} std::string s; char *c2 = s.data(); consume(c); // expected-warning {{Use of memory after it is freed}} // expected-note@-1 {{Use of memory after it is freed}} } - -void deref_after_scope_wchar_t_cstr() { - const wchar_t *w; +void deref_after_scope_wchar_t(bool cond) { + const wchar_t *c, *d; { -std::wstring ws; -w = ws.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} - std::wstring ws; - const wchar_t *w2 = ws.c_str(); - consume(w); // expected-warning {{Use of memory after it is freed}} - // expected-note@-1 {{Use of memory after it is freed}} -} - -void deref_after_scope_wchar_t_data() { - const wchar_t *w; - { -std::wstring ws; -w = ws.data(); // expected-note {{Pointer to dangling buffer was obtained here}} - } // expected-note {{Internal buffer is released because the object was destroyed}} - std::wstring ws; - const wchar_t
[PATCH] D48845: [Sema] Add fixit for unused lambda captures
acomminos updated this revision to Diff 155616. acomminos added a comment. Remove `const` qualifier for SourceRange. Repository: rC Clang https://reviews.llvm.org/D48845 Files: include/clang/Sema/DeclSpec.h include/clang/Sema/ScopeInfo.h include/clang/Sema/Sema.h lib/Parse/ParseExprCXX.cpp lib/Sema/SemaLambda.cpp test/FixIt/fixit-unused-lambda-capture.cpp Index: test/FixIt/fixit-unused-lambda-capture.cpp === --- /dev/null +++ test/FixIt/fixit-unused-lambda-capture.cpp @@ -0,0 +1,94 @@ +// RUN: cp %s %t +// RUN: %clang_cc1 -x c++ -fsyntax-only -Wunused-lambda-capture -Wno-unused-value -std=c++1z -fixit %t +// RUN: grep -v CHECK %t | FileCheck %s + +void test() { + int i = 0; + int j = 0; + int k = 0; + int c = 10; + int a[c]; + + [i,j] { return i; }; + // CHECK: [i] { return i; }; + [i,j] { return j; }; + // CHECK: [j] { return j; }; + [&i,j] { return j; }; + // CHECK: [j] { return j; }; + [j,&i] { return j; }; + // CHECK: [j] { return j; }; + [i,j,k] {}; + // CHECK: [] {}; + [i,j,k] { return i + j; }; + // CHECK: [i,j] { return i + j; }; + [i,j,k] { return j + k; }; + // CHECK: [j,k] { return j + k; }; + [i,j,k] { return i + k; }; + // CHECK: [i,k] { return i + k; }; + [i,j,k] { return i + j + k; }; + // CHECK: [i,j,k] { return i + j + k; }; + [&,i] { return k; }; + // CHECK: [&] { return k; }; + [=,&i] { return k; }; + // CHECK: [=] { return k; }; + [=,&i,&j] { return j; }; + // CHECK: [=,&j] { return j; }; + [=,&i,&j] { return i; }; + // CHECK: [=,&i] { return i; }; + [z = i] {}; + // CHECK: [] {}; + [i,z = i] { return z; }; + // CHECK: [z = i] { return z; }; + [z = i,i] { return z; }; + // CHECK: [z = i] { return z; }; + [&a] {}; + // CHECK: [] {}; + [i,&a] { return i; }; + // CHECK: [i] { return i; }; + [&a,i] { return i; }; + // CHECK: [i] { return i; }; + + #define I_MACRO() i + #define I_REF_MACRO() &i + [I_MACRO()] {}; + // CHECK: [] {}; + [I_MACRO(),j] { return j; }; + // CHECK: [j] { return j; }; + [j,I_MACRO()] { return j; }; + // CHECK: [j] { return j; }; + [I_REF_MACRO(),j] { return j; }; + // CHECK: [j] { return j; }; + [j,I_REF_MACRO()] { return j; }; + // CHECK: [j] { return j; }; + + int n = 0; + [z = (n = i),j] {}; + // CHECK: [z = (n = i)] {}; + [j,z = (n = i)] {}; + // CHECK: [z = (n = i)] {}; +} + +class ThisTest { + void test() { +int i = 0; + +[this] {}; +// CHECK: [] {}; +[i,this] { return i; }; +// CHECK: [i] { return i; }; +[this,i] { return i; }; +// CHECK: [i] { return i; }; +[*this] {}; +// CHECK: [] {}; +[*this,i] { return i; }; +// CHECK: [i] { return i; }; +[i,*this] { return i; }; +// CHECK: [i] { return i; }; +[*this] { return this; }; +// CHECK: [*this] { return this; }; +[*this,i] { return this; }; +// CHECK: [*this] { return this; }; +[i,*this] { return this; }; +// CHECK: [*this] { return this; }; + } +}; Index: lib/Sema/SemaLambda.cpp === --- lib/Sema/SemaLambda.cpp +++ lib/Sema/SemaLambda.cpp @@ -993,6 +993,7 @@ CheckCXXThisCapture(C->Loc, /*Explicit=*/true, /*BuildAndDiagnose*/ true, /*FunctionScopeIndexToStopAtPtr*/ nullptr, C->Kind == LCK_StarThis); + LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; continue; } @@ -1139,6 +1140,7 @@ TryCapture_ExplicitByVal; tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc); } +LSI->ExplicitCaptureRanges[LSI->Captures.size() - 1] = C->ExplicitRange; } finishLambdaExplicitCaptures(LSI); @@ -1478,19 +1480,22 @@ return false; } -void Sema::DiagnoseUnusedLambdaCapture(const Capture &From) { +bool Sema::DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, + const Capture &From) { if (CaptureHasSideEffects(From)) -return; +return false; if (From.isVLATypeCapture()) -return; +return false; auto diag = Diag(From.getLocation(), diag::warn_unused_lambda_capture); if (From.isThisCapture()) diag << "'this'"; else diag << From.getVariable(); diag << From.isNonODRUsed(); + diag << FixItHint::CreateRemoval(CaptureRange); + return true; } ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, @@ -1532,18 +1537,49 @@ // Translate captures. auto CurField = Class->field_begin(); +// True if the current capture has a used capture or default before it. +bool CurHasPreviousCapture = CaptureDefault != LCD_None; +SourceLocation PrevCaptureLoc = CurHasPreviousCapture ? +CaptureDefaultLoc : IntroducerRange.getBegin(); + for (unsigned I = 0, N = LSI->Captures.size(); I != N; ++I, ++CurField) { const Capture &From = LSI->Captures[I];
[PATCH] D49361: [analyzer][WIP] Detect pointers escaped after return statement execution in MallocChecker
rnkovacs created this revision. rnkovacs added reviewers: NoQ, xazax.hun, george.karpenkov. Herald added subscribers: mikhail.ramalho, a.sidorin, dkrupp, szepet, baloghadamsoftware, whisperity. Sometimes an object is destroyed right after the statement returning it is executed. This patch aims to make MallocChecker warn for these cases as well. FIXME1: Using two traits might not be the best solution. FIXME2: The warning is emitted at the end of the function, which might be confusing. Repository: rC Clang https://reviews.llvm.org/D49361 Files: lib/StaticAnalyzer/Checkers/MallocChecker.cpp test/Analysis/dangling-internal-buffer.cpp Index: test/Analysis/dangling-internal-buffer.cpp === --- test/Analysis/dangling-internal-buffer.cpp +++ test/Analysis/dangling-internal-buffer.cpp @@ -277,6 +277,13 @@ // expected-note@-1 {{Use of memory after it is freed}} } +const char *escape_via_return() { + std::string s; + return s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} +// expected-note@-1 {{Internal buffer is released because the object was destroyed}} +} // expected-warning {{Use of memory after it is freed}} +// expected-note@-1 {{Use of memory after it is freed}} + void deref_after_scope_ok(bool cond) { const char *c, *d; std::string s; Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp === --- lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -161,6 +161,7 @@ check::PointerEscape, check::ConstPointerEscape, check::PreStmt, + check::EndFunction, check::PreCall, check::PostStmt, check::PostStmt, @@ -217,6 +218,7 @@ void checkPostStmt(const BlockExpr *BE, CheckerContext &C) const; void checkDeadSymbols(SymbolReaper &SymReaper, CheckerContext &C) const; void checkPreStmt(const ReturnStmt *S, CheckerContext &C) const; + void checkEndFunction(CheckerContext &C) const; ProgramStateRef evalAssume(ProgramStateRef state, SVal Cond, bool Assumption) const; void checkLocation(SVal l, bool isLoad, const Stmt *S, @@ -556,12 +558,16 @@ }; }; }; + } // end anonymous namespace REGISTER_MAP_WITH_PROGRAMSTATE(RegionState, SymbolRef, RefState) REGISTER_MAP_WITH_PROGRAMSTATE(ReallocPairs, SymbolRef, ReallocPair) REGISTER_SET_WITH_PROGRAMSTATE(ReallocSizeZeroSymbols, SymbolRef) +REGISTER_TRAIT_WITH_PROGRAMSTATE(ReturnValue, const void *) +REGISTER_TRAIT_WITH_PROGRAMSTATE(ReturnExpr, const void *) + // A map from the freed symbol to the symbol representing the return value of // the free function. REGISTER_MAP_WITH_PROGRAMSTATE(FreeReturnValue, SymbolRef, SymbolRef) @@ -2471,8 +2477,22 @@ Sym = BMR->getSymbol(); // Check if we are returning freed memory. - if (Sym) + if (Sym) { +State = State->set(Sym); +State = State->set(E); +C.addTransition(State); + } +} + +void MallocChecker::checkEndFunction(CheckerContext &C) const { + ProgramStateRef State = C.getState(); + if (SymbolRef Sym = static_cast(State->get())) { +const Expr *E = static_cast(State->get()); checkUseAfterFree(Sym, C, E); +State = State->remove(); +State = State->remove(); +C.addTransition(State); + } } // TODO: Blocks should be either inlined or should call invalidate regions Index: test/Analysis/dangling-internal-buffer.cpp === --- test/Analysis/dangling-internal-buffer.cpp +++ test/Analysis/dangling-internal-buffer.cpp @@ -277,6 +277,13 @@ // expected-note@-1 {{Use of memory after it is freed}} } +const char *escape_via_return() { + std::string s; + return s.c_str(); // expected-note {{Pointer to dangling buffer was obtained here}} +// expected-note@-1 {{Internal buffer is released because the object was destroyed}} +} // expected-warning {{Use of memory after it is freed}} +// expected-note@-1 {{Use of memory after it is freed}} + void deref_after_scope_ok(bool cond) { const char *c, *d; std::string s; Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp === --- lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -161,6 +161,7 @@ check::PointerEscape, check::ConstPointerEscape, check::PreStmt, + check::EndFunction, check::PreCall,
[PATCH] D49361: [analyzer][WIP] Detect pointers escaped after return statement execution in MallocChecker
NoQ added a comment. Aha, so the destructors are called //after// the return statement! Makes sense. The return statement is available in `ExprEngine::processEndOfFunction()`, so i guess we could improve the `checkEndFunction()` callback to provide it, and then we wouldn't need any of those extra state traits: the returned expression would be a sub-expression of the return statement and the return value would be, well, the value of the returned expression (hopefully). The procedure of adding more arguments to a callback is a bit annoying but straightforward. I guess it'd be great to add a MallocChecker-only test. It should be possible by mocking a simple object that frees memory in its destructor (in a manner that the Analyzer can understand by inlining all methods of the object) and then returning that memory. > The warning is emitted at the end of the function, which might be confusing. I'm afraid it might be hard to fix; path-sensitive reports are usually thrown against the node and that node is already too far and the return statement node is too early. @george.karpenkov would your `getEndPath()`-fu help here? Repository: rC Clang https://reviews.llvm.org/D49361 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49360: [analyzer] Add support for more basic_string API in DanglingInternalBufferChecker
NoQ accepted this revision. NoQ added a comment. This revision is now accepted and ready to land. Cool! I don't have a strong preference with respect to whitelist vs. blacklist; your approach is safer but listing functions that don't immediately invalidate the buffer would allow us to avoid hard-to-detect false negatives while pretending that our users would notice and report easy-to-fix false positives for us. Also we rarely commit to adding a test for every single supported API function; bonus points for that, but usually 2-3 functions from a series of similar functions is enough :) Comment at: lib/StaticAnalyzer/Checkers/DanglingInternalBufferChecker.cpp:112-124 + if (const auto *MemOpCall = dyn_cast(&Call)) { +OverloadedOperatorKind Opc = MemOpCall->getOriginExpr()->getOperator(); +if (Opc == OO_Equal || Opc == OO_PlusEqual) + return true; +return false; + } + return (isa(Call) || Call.isCalled(AppendFn) || That quote from the Standard would look great here. Repository: rC Clang https://reviews.llvm.org/D49360 ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D49354: [MinGW] Automatically mangle Windows-specific entry points as C
This revision was automatically updated to reflect the committed changes. Closed by commit rL337146: [MinGW] Automatically mangle Windows-specific entry points as C (authored by mstorsjo, committed by ). Herald added a subscriber: llvm-commits. Changed prior to commit: https://reviews.llvm.org/D49354?vs=155598&id=155617#toc Repository: rL LLVM https://reviews.llvm.org/D49354 Files: cfe/trunk/lib/AST/ItaniumMangle.cpp cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp Index: cfe/trunk/lib/AST/ItaniumMangle.cpp === --- cfe/trunk/lib/AST/ItaniumMangle.cpp +++ cfe/trunk/lib/AST/ItaniumMangle.cpp @@ -592,6 +592,18 @@ if (FD->isMain()) return false; +// The Windows ABI expects that we would never mangle "typical" +// user-defined entry points regardless of visibility or freestanding-ness. +// +// N.B. This is distinct from asking about "main". "main" has a lot of +// special rules associated with it in the standard while these +// user-defined entry points are outside of the purview of the standard. +// For example, there can be only one definition for "main" in a standards +// compliant program; however nothing forbids the existence of wmain and +// WinMain in the same translation unit. +if (FD->isMSVCRTEntryPoint()) + return false; + // C++ functions and those whose names are not a simple identifier need // mangling. if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage) Index: cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp === --- cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp +++ cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-w64-mingw32 | FileCheck %s + +int func() { return 0; } +// CHECK-DAG: @_Z4funcv + +int main() { return 0; } +// CHECK-DAG: @main + +int wmain() { return 0; } +// CHECK-DAG: @wmain + +int WinMain() { return 0; } +// CHECK-DAG: @WinMain + +int wWinMain() { return 0; } +// CHECK-DAG: @wWinMain + +int DllMain() { return 0; } +// CHECK-DAG: @DllMain Index: cfe/trunk/lib/AST/ItaniumMangle.cpp === --- cfe/trunk/lib/AST/ItaniumMangle.cpp +++ cfe/trunk/lib/AST/ItaniumMangle.cpp @@ -592,6 +592,18 @@ if (FD->isMain()) return false; +// The Windows ABI expects that we would never mangle "typical" +// user-defined entry points regardless of visibility or freestanding-ness. +// +// N.B. This is distinct from asking about "main". "main" has a lot of +// special rules associated with it in the standard while these +// user-defined entry points are outside of the purview of the standard. +// For example, there can be only one definition for "main" in a standards +// compliant program; however nothing forbids the existence of wmain and +// WinMain in the same translation unit. +if (FD->isMSVCRTEntryPoint()) + return false; + // C++ functions and those whose names are not a simple identifier need // mangling. if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage) Index: cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp === --- cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp +++ cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-w64-mingw32 | FileCheck %s + +int func() { return 0; } +// CHECK-DAG: @_Z4funcv + +int main() { return 0; } +// CHECK-DAG: @main + +int wmain() { return 0; } +// CHECK-DAG: @wmain + +int WinMain() { return 0; } +// CHECK-DAG: @WinMain + +int wWinMain() { return 0; } +// CHECK-DAG: @wWinMain + +int DllMain() { return 0; } +// CHECK-DAG: @DllMain ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
r337146 - [MinGW] Automatically mangle Windows-specific entry points as C
Author: mstorsjo Date: Sun Jul 15 22:42:25 2018 New Revision: 337146 URL: http://llvm.org/viewvc/llvm-project?rev=337146&view=rev Log: [MinGW] Automatically mangle Windows-specific entry points as C This mangles entry points wmain, WinMain, wWinMain or DllMain as C functions, to match the ABI for these functions. We already did the same for these functions in MSVC mode, but we also should do the same in the Itanium ABI. This fixes PR38124. Differential Revision: https://reviews.llvm.org/D49354 Added: cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=337146&r1=337145&r2=337146&view=diff == --- cfe/trunk/lib/AST/ItaniumMangle.cpp (original) +++ cfe/trunk/lib/AST/ItaniumMangle.cpp Sun Jul 15 22:42:25 2018 @@ -592,6 +592,18 @@ bool ItaniumMangleContextImpl::shouldMan if (FD->isMain()) return false; +// The Windows ABI expects that we would never mangle "typical" +// user-defined entry points regardless of visibility or freestanding-ness. +// +// N.B. This is distinct from asking about "main". "main" has a lot of +// special rules associated with it in the standard while these +// user-defined entry points are outside of the purview of the standard. +// For example, there can be only one definition for "main" in a standards +// compliant program; however nothing forbids the existence of wmain and +// WinMain in the same translation unit. +if (FD->isMSVCRTEntryPoint()) + return false; + // C++ functions and those whose names are not a simple identifier need // mangling. if (!FD->getDeclName().isIdentifier() || L == CXXLanguageLinkage) Added: cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp?rev=337146&view=auto == --- cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp (added) +++ cfe/trunk/test/CodeGenCXX/mangle-mingw.cpp Sun Jul 15 22:42:25 2018 @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-w64-mingw32 | FileCheck %s + +int func() { return 0; } +// CHECK-DAG: @_Z4funcv + +int main() { return 0; } +// CHECK-DAG: @main + +int wmain() { return 0; } +// CHECK-DAG: @wmain + +int WinMain() { return 0; } +// CHECK-DAG: @WinMain + +int wWinMain() { return 0; } +// CHECK-DAG: @wWinMain + +int DllMain() { return 0; } +// CHECK-DAG: @DllMain ___ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits