From: Sebastian Redl Date: Wed, 27 May 2009 19:34:06 +0000 (+0000) Subject: Add a big test case for I-C-Es in C++, and a fix to make it work. The fix might not... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1590d9c0fec4c710c2962e4bb71f76979b5163d3;p=clang Add a big test case for I-C-Es in C++, and a fix to make it work. The fix might not be the right way to do it. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72490 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 11001ce52a..ab184563da 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -46,9 +46,12 @@ class ASTRecordLayout { FieldCount = N; FieldOffsets = new uint64_t[N]; } - + /// Finalize record layout. Adjust record size based on the alignment. - void FinalizeLayout() { + void FinalizeLayout(bool ForceNonEmpty = false) { + // In C++, records cannot be of size 0. + if (ForceNonEmpty && Size == 0) + Size = 8; // Finally, round the size of the record up to the alignment of the // record itself. Size = (Size + (Alignment-1)) & ~(Alignment-1); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index c168e98ea4..0db5f9b2bf 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -360,6 +360,7 @@ ASTContext::getTypeInfo(const Type *T) { case BuiltinType::NullPtr: Width = Target.getPointerWidth(0); // C++ 3.9.1p11: sizeof(nullptr_t) Align = Target.getPointerAlign(0); // == sizeof(void*) + break; } break; case Type::FixedWidthInt: @@ -768,7 +769,7 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D) { // Finally, round the size of the total struct up to the alignment of the // struct itself. - NewEntry->FinalizeLayout(); + NewEntry->FinalizeLayout(getLangOptions().CPlusPlus); return *NewEntry; } diff --git a/test/SemaCXX/constant-expression.cpp b/test/SemaCXX/constant-expression.cpp new file mode 100644 index 0000000000..02ea802c72 --- /dev/null +++ b/test/SemaCXX/constant-expression.cpp @@ -0,0 +1,83 @@ +// RUN: clang-cc -fsyntax-only -verify -std=c++98 %s + +// C++ [expr.const]p1: +// In several places, C++ requires expressions that evaluate to an integral +// or enumeration constant: as array bounds, as case expressions, as +// bit-field lengths, as enumerator initializers, as static member +// initializers, and as integral or enumeration non-type template arguments. +// An integral constant-expression can involve only literals, enumerators, +// const variables or static data members of integral or enumeration types +// initialized with constant expressions, and sizeof expressions. Floating +// literals can appear only if they are cast to integral or enumeration types. + +enum Enum { eval = 1 }; +const int cval = 2; +const Enum ceval = eval; +struct Struct { + static const int sval = 3; + static const Enum seval = eval; +}; + +template struct C { + enum E { + v1 = 1, + v2 = eval, + v3 = cval, + v4 = ceval, + v5 = Struct::sval, + v6 = Struct::seval, + v7 = itval, + v8 = etval, + v9 = (int)1.5, + v10 = sizeof(Struct), + v11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + }; + unsigned + b1 : 1, + b2 : eval, + b3 : cval, + b4 : ceval, + b5 : Struct::sval, + b6 : Struct::seval, + b7 : itval, + b8 : etval, + b9 : (int)1.5, + b10 : sizeof(Struct), + b11 : true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + ; + static const int + i1 = 1, + i2 = eval, + i3 = cval, + i4 = ceval, + i5 = Struct::sval, + i6 = Struct::seval, + i7 = itval, + i8 = etval, + i9 = (int)1.5, + i10 = sizeof(Struct), + i11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 + ; + void f() { + switch(0) { + case 0 + 1: + case 100 + eval: + case 200 + cval: + case 300 + ceval: + case 400 + Struct::sval: + case 500 + Struct::seval: + case 600 + itval: + case 700 + etval: + case 800 + (int)1.5: + case 900 + sizeof(Struct): + case 1000 + (true? 1 + cval * Struct::sval ^ + itval / (int)1.5 - sizeof(Struct) : 0): + ; + } + } + typedef C T0; +}; + +template struct C<1, eval>; +//template struct C; +//template struct C;