aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Lewycky <nicholas@mxc.ca>2012-01-24 21:15:41 +0000
committerNick Lewycky <nicholas@mxc.ca>2012-01-24 21:15:41 +0000
commitfca84b232dd74c91b2e0f963a3f8c3bd351a9037 (patch)
treeb2c8fcdf21b6c35ec60f1077a99ca526d5d89944
parent89088797876bddb866ce821f050a4395b7514dc2 (diff)
Add a new warning, -Wover-aligned, which detects attempts to use the default
allocator to construct an object which declares more alignment than the default allocator actually provides. Fixes PR9527! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148857 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/Basic/DiagnosticGroups.td1
-rw-r--r--include/clang/Basic/DiagnosticSemaKinds.td5
-rw-r--r--lib/Sema/SemaExprCXX.cpp16
-rw-r--r--test/SemaCXX/Inputs/warn-new-overaligned-3.h12
-rw-r--r--test/SemaCXX/warn-new-overaligned-2.cpp22
-rw-r--r--test/SemaCXX/warn-new-overaligned-3.cpp20
-rw-r--r--test/SemaCXX/warn-new-overaligned.cpp73
7 files changed, 149 insertions, 0 deletions
diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td
index 4787b85711..d5a0eea4d5 100644
--- a/include/clang/Basic/DiagnosticGroups.td
+++ b/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/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 87522e5eb3..dec27e0737 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/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/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index bea0954c6f..919ef06957 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/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/test/SemaCXX/Inputs/warn-new-overaligned-3.h b/test/SemaCXX/Inputs/warn-new-overaligned-3.h
new file mode 100644
index 0000000000..024acc299f
--- /dev/null
+++ b/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/test/SemaCXX/warn-new-overaligned-2.cpp b/test/SemaCXX/warn-new-overaligned-2.cpp
new file mode 100644
index 0000000000..0a7643956d
--- /dev/null
+++ b/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/test/SemaCXX/warn-new-overaligned-3.cpp b/test/SemaCXX/warn-new-overaligned-3.cpp
new file mode 100644
index 0000000000..f3b0cb7dd1
--- /dev/null
+++ b/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/test/SemaCXX/warn-new-overaligned.cpp b/test/SemaCXX/warn-new-overaligned.cpp
new file mode 100644
index 0000000000..6ebae8b513
--- /dev/null
+++ b/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];
+}
+}