diff options
-rw-r--r-- | include/clang/AST/TypeNodes.def | 19 | ||||
-rw-r--r-- | lib/AST/ASTContext.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenTypes.cpp | 4 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 40 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateDeduction.cpp | 21 | ||||
-rw-r--r-- | test/CodeGenCXX/mangle.cpp | 40 |
6 files changed, 115 insertions, 13 deletions
diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 9cf2cb7bd7..8187caddc6 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -31,7 +31,11 @@ // type that is always dependent. Clients that do not need to deal // with uninstantiated C++ templates can ignore these types. // -// There is a fifth macro, independent of the others. Most clients +// NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) - A type that +// is non-canonical unless it is dependent. Defaults to TYPE because +// it is neither reliably dependent nor reliably non-canonical. +// +// There is a sixth macro, independent of the others. Most clients // will not need to use it. // // LEAF_TYPE(Class) - A type that never has inner types. Clients @@ -51,6 +55,10 @@ # define DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) #endif +#ifndef NON_CANONICAL_UNLESS_DEPENDENT_TYPE +# define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) TYPE(Class, Base) +#endif + TYPE(Builtin, Type) TYPE(Complex, Type) TYPE(Pointer, Type) @@ -72,16 +80,16 @@ TYPE(FunctionProto, FunctionType) TYPE(FunctionNoProto, FunctionType) DEPENDENT_TYPE(UnresolvedUsing, Type) NON_CANONICAL_TYPE(Typedef, Type) -NON_CANONICAL_TYPE(TypeOfExpr, Type) -NON_CANONICAL_TYPE(TypeOf, Type) -NON_CANONICAL_TYPE(Decltype, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type) ABSTRACT_TYPE(Tag, Type) TYPE(Record, TagType) TYPE(Enum, TagType) NON_CANONICAL_TYPE(Elaborated, Type) DEPENDENT_TYPE(TemplateTypeParm, Type) NON_CANONICAL_TYPE(SubstTemplateTypeParm, Type) -TYPE(TemplateSpecialization, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TemplateSpecialization, Type) NON_CANONICAL_TYPE(QualifiedName, Type) DEPENDENT_TYPE(Typename, Type) TYPE(ObjCInterface, Type) @@ -101,6 +109,7 @@ LEAF_TYPE(TemplateTypeParm) #undef LEAF_TYPE #endif +#undef NON_CANONICAL_UNLESS_DEPENDENT_TYPE #undef DEPENDENT_TYPE #undef NON_CANONICAL_TYPE #undef ABSTRACT_TYPE diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 22871a4a68..5cd52396a8 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -4522,6 +4522,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { switch (LHSClass) { #define TYPE(Class, Base) #define ABSTRACT_TYPE(Class, Base) +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: #define NON_CANONICAL_TYPE(Class, Base) case Type::Class: #define DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" @@ -4644,9 +4645,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS) { return QualType(); } - case Type::TemplateSpecialization: - assert(false && "Dependent types have no size"); - break; } return QualType(); diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index f30e03c8c9..4feca4dd7d 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -190,6 +190,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { #define ABSTRACT_TYPE(Class, Base) #define NON_CANONICAL_TYPE(Class, Base) case Type::Class: #define DEPENDENT_TYPE(Class, Base) case Type::Class: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Class, Base) case Type::Class: #include "clang/AST/TypeNodes.def" assert(false && "Non-canonical or dependent types aren't possible."); break; @@ -390,9 +391,6 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { NULL); return PtrDiffTy; } - - case Type::TemplateSpecialization: - assert(false && "Dependent types can't get here"); } // FIXME: implement. diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index d9a7991f78..64743c7696 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -455,7 +455,9 @@ void CXXNameMangler::mangleUnresolvedScope(NestedNameSpecifier *Qualifier) { mangleType(QualType(Qualifier->getAsType(), 0)); break; case NestedNameSpecifier::Identifier: - mangleUnresolvedScope(Qualifier->getPrefix()); + // Member expressions can have these without prefixes. + if (Qualifier->getPrefix()) + mangleUnresolvedScope(Qualifier->getPrefix()); mangleSourceName(Qualifier->getAsIdentifier()); break; } @@ -1123,6 +1125,42 @@ void CXXNameMangler::mangleType(const TypenameType *T) { Out << 'E'; } +void CXXNameMangler::mangleType(const TypeOfType *T) { + // FIXME: this is pretty unsatisfactory, but there isn't an obvious + // "extension with parameters" mangling. + Out << "u6typeof"; +} + +void CXXNameMangler::mangleType(const TypeOfExprType *T) { + // FIXME: this is pretty unsatisfactory, but there isn't an obvious + // "extension with parameters" mangling. + Out << "u6typeof"; +} + +void CXXNameMangler::mangleType(const DecltypeType *T) { + Expr *E = T->getUnderlyingExpr(); + + // type ::= Dt <expression> E # decltype of an id-expression + // # or class member access + // ::= DT <expression> E # decltype of an expression + + // This purports to be an exhaustive list of id-expressions and + // class member accesses. Note that we do not ignore parentheses; + // parentheses change the semantics of decltype for these + // expressions (and cause the mangler to use the other form). + if (isa<DeclRefExpr>(E) || + isa<MemberExpr>(E) || + isa<UnresolvedLookupExpr>(E) || + isa<DependentScopeDeclRefExpr>(E) || + isa<CXXDependentScopeMemberExpr>(E) || + isa<UnresolvedMemberExpr>(E)) + Out << "Dt"; + else + Out << "DT"; + mangleExpression(E); + Out << 'E'; +} + void CXXNameMangler::mangleIntegerLiteral(QualType T, const llvm::APSInt &Value) { // <expr-primary> ::= L <type> <value number> E # integer literal diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp index df4d4a828d..7f16400aea 100644 --- a/lib/Sema/SemaTemplateDeduction.cpp +++ b/lib/Sema/SemaTemplateDeduction.cpp @@ -2419,6 +2419,27 @@ MarkUsedTemplateParameters(Sema &SemaRef, QualType T, OnlyDeduced, Depth, Used); break; + case Type::TypeOf: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<TypeOfType>(T)->getUnderlyingType(), + OnlyDeduced, Depth, Used); + break; + + case Type::TypeOfExpr: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<TypeOfExprType>(T)->getUnderlyingExpr(), + OnlyDeduced, Depth, Used); + break; + + case Type::Decltype: + if (!OnlyDeduced) + MarkUsedTemplateParameters(SemaRef, + cast<DecltypeType>(T)->getUnderlyingExpr(), + OnlyDeduced, Depth, Used); + break; + // None of these types have any template parameters in them. case Type::Builtin: case Type::VariableArray: diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index d00579155c..e18ca03d1b 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks | FileCheck %s +// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin9 -fblocks -std=c++0x | FileCheck %s struct X { }; struct Y { }; @@ -376,3 +376,41 @@ namespace test1 { // CHECK: define internal void @_Z27functionWithInternalLinkagev() static void functionWithInternalLinkage() { } void g() { functionWithInternalLinkage(); } + +namespace test2 { + template <class T> decltype(((T*) 0)->member) read_member(T& obj) { + return obj.member; + } + + struct A { int member; } obj; + int test() { + return read_member(obj); + } + + // CHECK: define linkonce_odr i32 @_ZN5test211read_memberINS_1AEEEDtptcvPT_Li0E6memberERS2_( +} + +namespace test3 { + struct AmbiguousBase { int ab; }; + struct Path1 : AmbiguousBase { float p; }; + struct Path2 : AmbiguousBase { double p; }; + struct Derived : Path1, Path2 { }; + + //template <class T> decltype(((T*) 0)->Path1::ab) get_ab_1(T &ref) { return ref.Path1::ab; } + //template <class T> decltype(((T*) 0)->Path2::ab) get_ab_2(T &ref) { return ref.Path2::ab; } + + // define linkonce_odr float @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path11pERS2_( + template <class T> decltype(((T*) 0)->Path1::p) get_p_1(T &ref) { return ref.Path1::p; } + + // define linkonce_odr double @_ZN5test37get_p_1INS_7DerivedEEEDtptcvPT_Li0E5Path21pERS2_( + template <class T> decltype(((T*) 0)->Path2::p) get_p_2(T &ref) { return ref.Path2::p; } + + Derived obj; + void test() { + // FIXME: uncomment these when we support diamonds competently + //get_ab_1(obj); + //get_ab_2(obj); + get_p_1(obj); + get_p_2(obj); + } +} |