summaryrefslogtreecommitdiffstats
path: root/lib/Sema/SemaType.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema/SemaType.cpp')
-rw-r--r--lib/Sema/SemaType.cpp154
1 files changed, 88 insertions, 66 deletions
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index a4fc98c..aa30b5c 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -11,7 +11,8 @@
//
//===----------------------------------------------------------------------===//
-#include "Sema.h"
+#include "clang/Sema/SemaInternal.h"
+#include "clang/Sema/Template.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
@@ -20,13 +21,12 @@
#include "clang/AST/TypeLocVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/PartialDiagnostic.h"
-#include "clang/Parse/DeclSpec.h"
+#include "clang/Basic/TargetInfo.h"
+#include "clang/Sema/DeclSpec.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
-#include <iostream>
-
/// \brief Perform adjustment on the parameter type of a function.
///
/// This routine adjusts the given parameter type @p T to the actual
@@ -266,8 +266,7 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
case DeclSpec::TST_enum:
case DeclSpec::TST_union:
case DeclSpec::TST_struct: {
- TypeDecl *D
- = dyn_cast_or_null<TypeDecl>(static_cast<Decl *>(DS.getTypeRep()));
+ TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
if (!D) {
// This can happen in C++ with ambiguous lookups.
Result = Context.IntTy;
@@ -299,9 +298,11 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
- Result = TheSema.GetTypeFromParser(DS.getTypeRep());
-
- if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
+ Result = TheSema.GetTypeFromParser(DS.getRepAsType());
+ if (Result.isNull())
+ TheDeclarator.setInvalidType(true);
+ else if (DeclSpec::ProtocolQualifierListTy PQ
+ = DS.getProtocolQualifiers()) {
if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
// Silently drop any existing protocol qualifiers.
// TODO: determine whether that's the right thing to do.
@@ -336,13 +337,13 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
}
case DeclSpec::TST_typeofType:
// FIXME: Preserve type source info.
- Result = TheSema.GetTypeFromParser(DS.getTypeRep());
+ Result = TheSema.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for typeof?");
// TypeQuals handled by caller.
Result = Context.getTypeOfType(Result);
break;
case DeclSpec::TST_typeofExpr: {
- Expr *E = static_cast<Expr *>(DS.getTypeRep());
+ Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for typeof?");
// TypeQuals handled by caller.
Result = TheSema.BuildTypeofExprType(E);
@@ -353,7 +354,7 @@ static QualType ConvertDeclSpecToType(Sema &TheSema,
break;
}
case DeclSpec::TST_decltype: {
- Expr *E = static_cast<Expr *>(DS.getTypeRep());
+ Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for decltype?");
// TypeQuals handled by caller.
Result = TheSema.BuildDecltypeType(E);
@@ -674,10 +675,9 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
!ArraySize->getType()->isIntegerType()) {
Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
<< ArraySize->getType() << ArraySize->getSourceRange();
- ArraySize->Destroy(Context);
return QualType();
}
- llvm::APSInt ConstVal(32);
+ llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
if (!ArraySize) {
if (ASM == ArrayType::Star)
T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
@@ -707,7 +707,17 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
isSFINAEContext()? diag::err_typecheck_zero_array_size
: diag::ext_typecheck_zero_array_size)
<< ArraySize->getSourceRange();
+ } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
+ !T->isIncompleteType()) {
+ // Is the array too large?
+ unsigned ActiveSizeBits
+ = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
+ if (ActiveSizeBits > ConstantArrayType::getMaxSizeBits(Context))
+ Diag(ArraySize->getLocStart(), diag::err_array_too_large)
+ << ConstVal.toString(10)
+ << ArraySize->getSourceRange();
}
+
T = Context.getConstantArrayType(T, ConstVal, ASM, Quals);
}
// If this is not C99, extwarn about VLA's and C99 array size modifiers.
@@ -740,11 +750,8 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
/// \brief Build an ext-vector type.
///
/// Run the required checks for the extended vector type.
-QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
+QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc) {
-
- Expr *Arg = (Expr *)ArraySize.get();
-
// unlike gcc's vector_size attribute, we do not allow vectors to be defined
// in conjunction with complex types (pointers, arrays, functions, etc.).
if (!T->isDependentType() &&
@@ -753,11 +760,11 @@ QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
return QualType();
}
- if (!Arg->isTypeDependent() && !Arg->isValueDependent()) {
+ if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
llvm::APSInt vecSize(32);
- if (!Arg->isIntegerConstantExpr(vecSize, Context)) {
+ if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_not_int)
- << "ext_vector_type" << Arg->getSourceRange();
+ << "ext_vector_type" << ArraySize->getSourceRange();
return QualType();
}
@@ -767,7 +774,7 @@ QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
if (vectorSize == 0) {
Diag(AttrLoc, diag::err_attribute_zero_size)
- << Arg->getSourceRange();
+ << ArraySize->getSourceRange();
return QualType();
}
@@ -775,8 +782,7 @@ QualType Sema::BuildExtVectorType(QualType T, ExprArg ArraySize,
return Context.getExtVectorType(T, vectorSize);
}
- return Context.getDependentSizedExtVectorType(T, ArraySize.takeAs<Expr>(),
- AttrLoc);
+ return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
}
/// \brief Build a function type.
@@ -812,7 +818,8 @@ QualType Sema::BuildFunctionType(QualType T,
QualType *ParamTypes,
unsigned NumParamTypes,
bool Variadic, unsigned Quals,
- SourceLocation Loc, DeclarationName Entity) {
+ SourceLocation Loc, DeclarationName Entity,
+ const FunctionType::ExtInfo &Info) {
if (T->isArrayType() || T->isFunctionType()) {
Diag(Loc, diag::err_func_returning_array_function)
<< T->isFunctionType() << T;
@@ -834,8 +841,7 @@ QualType Sema::BuildFunctionType(QualType T,
return QualType();
return Context.getFunctionType(T, ParamTypes, NumParamTypes, Variadic,
- Quals, false, false, 0, 0,
- FunctionType::ExtInfo());
+ Quals, false, false, 0, 0, Info);
}
/// \brief Build a member pointer type \c T Class::*.
@@ -883,6 +889,14 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
return QualType();
}
+ // In the Microsoft ABI, the class is allowed to be an incomplete
+ // type. In such cases, the compiler makes a worst-case assumption.
+ // We make no such assumption right now, so emit an error if the
+ // class isn't a complete type.
+ if (Context.Target.getCXXABI() == CXXABI_Microsoft &&
+ RequireCompleteType(Loc, Class, diag::err_incomplete_type))
+ return QualType();
+
return Context.getMemberPointerType(T, Class.getTypePtr());
}
@@ -912,8 +926,8 @@ QualType Sema::BuildBlockPointerType(QualType T,
return Context.getBlockPointerType(T);
}
-QualType Sema::GetTypeFromParser(TypeTy *Ty, TypeSourceInfo **TInfo) {
- QualType QT = QualType::getFromOpaquePtr(Ty);
+QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
+ QualType QT = Ty.get();
if (QT.isNull()) {
if (TInfo) *TInfo = 0;
return QualType();
@@ -955,7 +969,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
T = ConvertDeclSpecToType(*this, D, FnAttrsFromDeclSpec);
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
- TagDecl* Owned = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
+ TagDecl* Owned = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
// Owned is embedded if it was defined here, or if it is the
// very first (i.e., canonical) declaration of this tag type.
Owned->setEmbeddedInDeclarator(Owned->isDefinition() ||
@@ -1174,7 +1188,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
if (getLangOptions().CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
// C++ [dcl.fct]p6:
// Types shall not be defined in return or parameter types.
- TagDecl *Tag = cast<TagDecl>((Decl *)D.getDeclSpec().getTypeRep());
+ TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
if (Tag->isDefinition())
Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
<< Context.getTypeDeclType(Tag);
@@ -1221,8 +1235,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
ArgTys.reserve(FTI.NumArgs);
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param =
- cast<ParmVarDecl>(FTI.ArgInfo[i].Param.getAs<Decl>());
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
QualType ArgTy = Param->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
@@ -1295,19 +1308,19 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
}
case DeclaratorChunk::MemberPointer:
// The scope spec must refer to a class, or be dependent.
+ CXXScopeSpec &SS = DeclType.Mem.Scope();
QualType ClsType;
- if (DeclType.Mem.Scope().isInvalid()) {
+ if (SS.isInvalid()) {
// Avoid emitting extra errors if we already errored on the scope.
D.setInvalidType(true);
- } else if (isDependentScopeSpecifier(DeclType.Mem.Scope())
- || dyn_cast_or_null<CXXRecordDecl>(
- computeDeclContext(DeclType.Mem.Scope()))) {
+ } else if (isDependentScopeSpecifier(SS) ||
+ dyn_cast_or_null<CXXRecordDecl>(computeDeclContext(SS))) {
NestedNameSpecifier *NNS
- = (NestedNameSpecifier *)DeclType.Mem.Scope().getScopeRep();
+ = static_cast<NestedNameSpecifier*>(SS.getScopeRep());
NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
- ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
+ ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
NNS->getAsIdentifier());
break;
@@ -1315,11 +1328,15 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S,
case NestedNameSpecifier::Global:
llvm_unreachable("Nested-name-specifier must name a type");
break;
-
+
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
ClsType = QualType(NNS->getAsType(), 0);
- if (NNSPrefix)
+ // Note: if NNS is dependent, then its prefix (if any) is already
+ // included in ClsType; this does not hold if the NNS is
+ // nondependent: in this case (if there is indeed a prefix)
+ // ClsType needs to be wrapped into an elaborated type.
+ if (NNSPrefix && !NNS->isDependent())
ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
break;
}
@@ -1455,7 +1472,7 @@ namespace {
}
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
// If we got no declarator info from previous Sema routines,
// just fill with the typespec loc.
@@ -1483,9 +1500,9 @@ namespace {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
- assert(DS.getTypeRep());
+ assert(DS.getRepAsType());
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
@@ -1508,7 +1525,7 @@ namespace {
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (Keyword == ETK_Typename) {
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc()));
return;
@@ -1526,7 +1543,7 @@ namespace {
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (Keyword == ETK_Typename) {
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc()));
return;
@@ -1546,7 +1563,7 @@ namespace {
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (Keyword == ETK_Typename) {
TypeSourceInfo *TInfo = 0;
- Sema::GetTypeFromParser(DS.getTypeRep(), &TInfo);
+ Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(cast<DependentTemplateSpecializationTypeLoc>(
TInfo->getTypeLoc()));
@@ -1620,7 +1637,7 @@ namespace {
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
- ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+ ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
TL.setArg(tpi++, Param);
}
// FIXME: exception specs
@@ -1651,24 +1668,21 @@ Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
- TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);
-
- // We have source information for the return type that was not in the
- // declaration specifiers; copy that information into the current type
- // location so that it will be retained. This occurs, for example, with
- // a C++ conversion function, where the return type occurs within the
- // declarator-id rather than in the declaration specifiers.
- if (ReturnTypeInfo && D.getDeclSpec().getTypeSpecType() == TST_unspecified) {
+ // If we have different source information for the return type, use
+ // that. This really only applies to C++ conversion functions.
+ if (ReturnTypeInfo) {
TypeLoc TL = ReturnTypeInfo->getTypeLoc();
assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
+ } else {
+ TypeSpecLocFiller(D.getDeclSpec()).Visit(CurrTL);
}
return TInfo;
}
/// \brief Create a LocInfoType to hold the given QualType and TypeSourceInfo.
-QualType Sema::CreateLocInfoType(QualType T, TypeSourceInfo *TInfo) {
+ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
// FIXME: LocInfoTypes are "transient", only needed for passing to/from Parser
// and Sema during declaration parsing. Try deallocating/caching them when
// it's appropriate, instead of allocating them and keeping them around.
@@ -1676,7 +1690,7 @@ QualType Sema::CreateLocInfoType(QualType T, TypeSourceInfo *TInfo) {
new (LocT) LocInfoType(T, TInfo);
assert(LocT->getTypeClass() != T->getTypeClass() &&
"LocInfoType's TypeClass conflicts with an existing Type class");
- return QualType(LocT, 0);
+ return ParsedType::make(QualType(LocT, 0));
}
void LocInfoType::getAsStringInternal(std::string &Str,
@@ -1686,7 +1700,7 @@ void LocInfoType::getAsStringInternal(std::string &Str,
" GetTypeFromParser");
}
-Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
+TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
// C99 6.7.6: Type names have no identifier. This is already validated by
// the parser.
assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
@@ -1710,8 +1724,7 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
<< Context.getTypeDeclType(OwnedTag);
}
- T = CreateLocInfoType(T, TInfo);
- return T.getAsOpaquePtr();
+ return CreateParsedType(T, TInfo);
}
@@ -1825,9 +1838,10 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
// Delay if this is not a function or pointer to block.
if (!Type->isFunctionPointerType()
&& !Type->isBlockPointerType()
- && !Type->isFunctionType())
+ && !Type->isFunctionType()
+ && !Type->isMemberFunctionPointerType())
return true;
-
+
// Otherwise we can process right away.
Type = S.Context.getNoReturnType(Type);
return false;
@@ -1842,7 +1856,8 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
// Delay if this is not a function or pointer to block.
if (!Type->isFunctionPointerType()
&& !Type->isBlockPointerType()
- && !Type->isFunctionType())
+ && !Type->isFunctionType()
+ && !Type->isMemberFunctionPointerType())
return true;
// Otherwise we can process right away.
@@ -1868,6 +1883,12 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
QualType T = Type;
if (const PointerType *PT = Type->getAs<PointerType>())
T = PT->getPointeeType();
+ else if (const BlockPointerType *BPT = Type->getAs<BlockPointerType>())
+ T = BPT->getPointeeType();
+ else if (const MemberPointerType *MPT = Type->getAs<MemberPointerType>())
+ T = MPT->getPointeeType();
+ else if (const ReferenceType *RT = Type->getAs<ReferenceType>())
+ T = RT->getPointeeType();
const FunctionType *Fn = T->getAs<FunctionType>();
// Delay if the type didn't work out to a function.
@@ -1880,6 +1901,7 @@ bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
case AttributeList::AT_fastcall: CC = CC_X86FastCall; break;
case AttributeList::AT_stdcall: CC = CC_X86StdCall; break;
case AttributeList::AT_thiscall: CC = CC_X86ThisCall; break;
+ case AttributeList::AT_pascal: CC = CC_X86Pascal; break;
default: llvm_unreachable("unexpected attribute kind"); return false;
}
@@ -1946,8 +1968,7 @@ static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
return;
}
// the base type must be integer or float, and can't already be a vector.
- if (CurType->isVectorType() ||
- (!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
+ if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
@@ -2008,6 +2029,7 @@ void ProcessTypeAttributeList(Sema &S, QualType &Result,
case AttributeList::AT_fastcall:
case AttributeList::AT_stdcall:
case AttributeList::AT_thiscall:
+ case AttributeList::AT_pascal:
case AttributeList::AT_regparm:
// Don't process these on the DeclSpec.
if (IsDeclSpec ||
OpenPOWER on IntegriCloud