From: Nick Lewycky Date: Tue, 24 Jan 2012 21:15:41 +0000 (+0000) Subject: Add a new warning, -Wover-aligned, which detects attempts to use the default X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=fca84b232dd74c91b2e0f963a3f8c3bd351a9037;p=clang 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 --- 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, DefaultIgnore; +def warn_overaligned_type : Warning< + "type %0 requires %1 bytes of alignment and the default allocator only " + "guarantees %2 bytes">, + InGroup, 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 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 + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines 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 +// where the header here simulates . +#include + +struct Test { + template + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines 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 + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + SeparateCacheLines 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 + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + void* operator new(unsigned long) { + return 0; + } + + SeparateCacheLines 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 + struct SeparateCacheLines { + T data; + } __attribute__((aligned(256))); + + void* operator new[](unsigned long) { + return 0; + } + + SeparateCacheLines 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]; +} +}