diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticGroups.td | 1 | ||||
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 16 | ||||
-rw-r--r-- | clang/test/SemaCXX/Inputs/warn-new-overaligned-3.h | 12 | ||||
-rw-r--r-- | clang/test/SemaCXX/warn-new-overaligned-2.cpp | 22 | ||||
-rw-r--r-- | clang/test/SemaCXX/warn-new-overaligned-3.cpp | 20 | ||||
-rw-r--r-- | clang/test/SemaCXX/warn-new-overaligned.cpp | 73 |
7 files changed, 149 insertions, 0 deletions
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 4787b857110..d5a0eea4d59 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -122,6 +122,7 @@ def InitializerOverrides : DiagGroup<"initializer-overrides">; def NonNull : DiagGroup<"nonnull">; def : DiagGroup<"nonportable-cfstrings">; def NonVirtualDtor : DiagGroup<"non-virtual-dtor">; +def OveralignedType : DiagGroup<"over-aligned">; def : DiagGroup<"old-style-cast">; def : DiagGroup<"old-style-definition">; def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 87522e5eb39..dec27e07375 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4024,6 +4024,11 @@ def note_hidden_overloaded_virtual_declared_here : Note< def warn_using_directive_in_header : Warning< "using namespace directive in global context in header">, InGroup<HeaderHygiene>, DefaultIgnore; +def warn_overaligned_type : Warning< + "type %0 requires %1 bytes of alignment and the default allocator only " + "guarantees %2 bytes">, + InGroup<OveralignedType>, DefaultIgnore; +def note_overaligned_type : Note<"over-aligned here">; def err_conditional_void_nonvoid : Error< "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand " diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index bea0954c6f0..919ef06957c 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -20,6 +20,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/TemplateDeduction.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/CharUnits.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" @@ -1104,6 +1105,21 @@ Sema::BuildCXXNew(SourceLocation StartLoc, bool UseGlobal, PlaceArgs = &AllPlaceArgs[0]; } + // Warn if the type is over-aligned and is being allocated by global operator + // new. + if (OperatorNew && + (OperatorNew->isImplicit() || + getSourceManager().isInSystemHeader(OperatorNew->getLocStart()))) { + if (unsigned Align = Context.getPreferredTypeAlign(AllocType.getTypePtr())){ + unsigned SuitableAlign = Context.getTargetInfo().getSuitableAlign(); + if (Align > SuitableAlign) + Diag(StartLoc, diag::warn_overaligned_type) + << AllocType + << unsigned(Align / Context.getCharWidth()) + << unsigned(SuitableAlign / Context.getCharWidth()); + } + } + bool Init = ConstructorLParen.isValid(); // --- Choosing a constructor --- CXXConstructorDecl *Constructor = 0; diff --git a/clang/test/SemaCXX/Inputs/warn-new-overaligned-3.h b/clang/test/SemaCXX/Inputs/warn-new-overaligned-3.h new file mode 100644 index 00000000000..024acc299fe --- /dev/null +++ b/clang/test/SemaCXX/Inputs/warn-new-overaligned-3.h @@ -0,0 +1,12 @@ +#pragma GCC system_header + +// This header file pretends to be <new> from the system library, for the +// purpose of the over-aligned warnings test. + +void* operator new(unsigned long) { + return 0; +} +void* operator new[](unsigned long) { + return 0; +} + diff --git a/clang/test/SemaCXX/warn-new-overaligned-2.cpp b/clang/test/SemaCXX/warn-new-overaligned-2.cpp new file mode 100644 index 00000000000..0a7643956db --- /dev/null +++ b/clang/test/SemaCXX/warn-new-overaligned-2.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -Wover-aligned -verify %s + +// This test verifies that we don't warn when the global operator new is +// overridden. That's why we can't merge this with the other test file. + +void* operator new(unsigned long); +void* operator new[](unsigned long); + +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; + new Test[10]; +} diff --git a/clang/test/SemaCXX/warn-new-overaligned-3.cpp b/clang/test/SemaCXX/warn-new-overaligned-3.cpp new file mode 100644 index 00000000000..f3b0cb7dd18 --- /dev/null +++ b/clang/test/SemaCXX/warn-new-overaligned-3.cpp @@ -0,0 +1,20 @@ +// RUN: %clang_cc1 -Wover-aligned %s -isystem %S/Inputs -verify + +// This test ensures that we still get the warning even if we #include <new> +// where the header here simulates <new>. +#include <warn-new-overaligned-3.h> + +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; // expected-warning {{type 'Test' requires 256 bytes of alignment and the default allocator only guarantees}} + new Test[10]; // expected-warning {{type 'Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} diff --git a/clang/test/SemaCXX/warn-new-overaligned.cpp b/clang/test/SemaCXX/warn-new-overaligned.cpp new file mode 100644 index 00000000000..6ebae8b513a --- /dev/null +++ b/clang/test/SemaCXX/warn-new-overaligned.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -Wover-aligned -verify %s + +namespace test1 { +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} + new Test[10]; // expected-warning {{type 'test1::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test2 { +class Test { + typedef int __attribute__((aligned(256))) aligned_int; + aligned_int high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; // expected-warning {{type 'test2::Test' requires 256 bytes of alignment and the default allocator only guarantees}} + new Test[10]; // expected-warning {{type 'test2::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test3 { +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + void* operator new(unsigned long) { + return 0; + } + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; + new Test[10]; // expected-warning {{type 'test3::Test' requires 256 bytes of alignment and the default allocator only guarantees}} +} +} + +namespace test4 { +struct Test { + template <typename T> + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + void* operator new[](unsigned long) { + return 0; + } + + SeparateCacheLines<int> high_contention_data[10]; +}; + +void helper() { + Test t; + new Test; // expected-warning {{type 'test4::Test' requires 256 bytes of alignment and the default allocator only guarantees}} + new Test[10]; +} +} |