This change partly addresses a heinous problem we have with the
parsing of attribute arguments that are a lone identifier. Previously,
we would end up parsing the 'align' attribute of this as an expression
"(Align)":
template<unsigned Size, unsigned Align>
class my_aligned_storage
{
__attribute__((align((Align)))) char storage[Size];
};
while this would parse as a "parameter name" 'Align':
template<unsigned Size, unsigned Align>
class my_aligned_storage
{
__attribute__((align(Align))) char storage[Size];
};
The code that handles the alignment attribute would completely ignore
the parameter name, so the while the first of these would do what's
expected, the second would silently be equivalent to
template<unsigned Size, unsigned Align>
class my_aligned_storage
{
__attribute__((align)) char storage[Size];
};
i.e., use the maximal alignment rather than the specified alignment.
Address this by sniffing the "Args" provided in the TableGen
description of attributes. If the first argument is "obviously"
something that should be treated as an expression (rather than an
identifier to be matched later), parse it as an expression.
Fixes <rdar://problem/13700933>.
llvm-svn: 180973
55 lines
1.5 KiB
C++
55 lines
1.5 KiB
C++
// RUN: %clang_cc1 -std=gnu++11 -fsyntax-only -verify %s
|
|
|
|
namespace attribute_aligned {
|
|
template<int N>
|
|
struct X {
|
|
char c[1] __attribute__((__aligned__((N)))); // expected-error {{alignment is not a power of 2}}
|
|
};
|
|
|
|
template <bool X> struct check {
|
|
int check_failed[X ? 1 : -1]; // expected-error {{array with a negative size}}
|
|
};
|
|
|
|
template <int N> struct check_alignment {
|
|
typedef check<N == sizeof(X<N>)> t; // expected-note {{in instantiation}}
|
|
};
|
|
|
|
check_alignment<1>::t c1;
|
|
check_alignment<2>::t c2;
|
|
check_alignment<3>::t c3; // expected-note 2 {{in instantiation}}
|
|
check_alignment<4>::t c4;
|
|
|
|
template<unsigned Size, unsigned Align>
|
|
class my_aligned_storage
|
|
{
|
|
__attribute__((align(Align))) char storage[Size];
|
|
};
|
|
|
|
template<typename T>
|
|
class C {
|
|
public:
|
|
C() {
|
|
static_assert(sizeof(t) == sizeof(T), "my_aligned_storage size wrong");
|
|
static_assert(alignof(t) == alignof(T), "my_aligned_storage align wrong"); // expected-warning{{'alignof' applied to an expression is a GNU extension}}
|
|
}
|
|
|
|
private:
|
|
my_aligned_storage<sizeof(T), alignof(T)> t;
|
|
};
|
|
|
|
C<double> cd;
|
|
}
|
|
|
|
namespace PR9049 {
|
|
extern const void *CFRetain(const void *ref);
|
|
|
|
template<typename T> __attribute__((cf_returns_retained))
|
|
inline T WBCFRetain(T aValue) { return aValue ? (T)CFRetain(aValue) : (T)0; }
|
|
|
|
|
|
extern void CFRelease(const void *ref);
|
|
|
|
template<typename T>
|
|
inline void WBCFRelease(__attribute__((cf_consumed)) T aValue) { if(aValue) CFRelease(aValue); }
|
|
}
|