#include "clang/Sema/ScopeInfo.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/Sema/Template.h"
#include "clang/Basic/OpenCL.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTMutationListener.h"
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/TypeLoc.h"
#include "clang/AST/TypeLocVisitor.h"
#include "clang/AST/Expr.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Lex/Preprocessor.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/DeclSpec.h"
#include "clang/Sema/DelayedDiagnostic.h"
#include "clang/Sema/Lookup.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/ErrorHandling.h"
using namespace clang;
static bool isOmittedBlockReturnType(const Declarator &D) {
if (D.getContext() != Declarator::BlockLiteralContext ||
D.getDeclSpec().hasTypeSpecifier())
return false;
if (D.getNumTypeObjects() == 0)
return true;
if (D.getNumTypeObjects() == 1 &&
D.getTypeObject(0).Kind == DeclaratorChunk::Function)
return true;
return false;
}
static void diagnoseBadTypeAttribute(Sema &S, const AttributeList &attr,
QualType type) {
bool useExpansionLoc = false;
unsigned diagID = 0;
switch (attr.getKind()) {
case AttributeList::AT_ObjCGC:
diagID = diag::warn_pointer_attribute_wrong_type;
useExpansionLoc = true;
break;
case AttributeList::AT_ObjCOwnership:
diagID = diag::warn_objc_object_attribute_wrong_type;
useExpansionLoc = true;
break;
default:
diagID = diag::warn_function_attribute_wrong_type;
break;
}
SourceLocation loc = attr.getLoc();
StringRef name = attr.getName()->getName();
if (useExpansionLoc && loc.isMacroID() && attr.getParameterName()) {
if (attr.getParameterName()->isStr("strong")) {
if (S.findMacroSpelling(loc, "__strong")) name = "__strong";
} else if (attr.getParameterName()->isStr("weak")) {
if (S.findMacroSpelling(loc, "__weak")) name = "__weak";
}
}
S.Diag(loc, diagID) << name << type;
}
#define OBJC_POINTER_TYPE_ATTRS_CASELIST \
case AttributeList::AT_ObjCGC: \
case AttributeList::AT_ObjCOwnership
#define FUNCTION_TYPE_ATTRS_CASELIST \
case AttributeList::AT_NoReturn: \
case AttributeList::AT_CDecl: \
case AttributeList::AT_FastCall: \
case AttributeList::AT_StdCall: \
case AttributeList::AT_ThisCall: \
case AttributeList::AT_Pascal: \
case AttributeList::AT_Regparm: \
case AttributeList::AT_Pcs \
namespace {
class TypeProcessingState {
Sema &sema;
Declarator &declarator;
unsigned chunkIndex;
bool trivial;
bool hasSavedAttrs;
SmallVector<AttributeList*, 2> savedAttrs;
SmallVector<AttributeList*, 2> ignoredTypeAttrs;
public:
TypeProcessingState(Sema &sema, Declarator &declarator)
: sema(sema), declarator(declarator),
chunkIndex(declarator.getNumTypeObjects()),
trivial(true), hasSavedAttrs(false) {}
Sema &getSema() const {
return sema;
}
Declarator &getDeclarator() const {
return declarator;
}
unsigned getCurrentChunkIndex() const {
return chunkIndex;
}
void setCurrentChunkIndex(unsigned idx) {
assert(idx <= declarator.getNumTypeObjects());
chunkIndex = idx;
}
AttributeList *&getCurrentAttrListRef() const {
assert(chunkIndex <= declarator.getNumTypeObjects());
if (chunkIndex == declarator.getNumTypeObjects())
return getMutableDeclSpec().getAttributes().getListRef();
return declarator.getTypeObject(chunkIndex).getAttrListRef();
}
void saveDeclSpecAttrs() {
if (hasSavedAttrs) return;
DeclSpec &spec = getMutableDeclSpec();
for (AttributeList *attr = spec.getAttributes().getList(); attr;
attr = attr->getNext())
savedAttrs.push_back(attr);
trivial &= savedAttrs.empty();
hasSavedAttrs = true;
}
void addIgnoredTypeAttr(AttributeList &attr) {
ignoredTypeAttrs.push_back(&attr);
}
void diagnoseIgnoredTypeAttrs(QualType type) const {
for (SmallVectorImpl<AttributeList*>::const_iterator
i = ignoredTypeAttrs.begin(), e = ignoredTypeAttrs.end();
i != e; ++i)
diagnoseBadTypeAttribute(getSema(), **i, type);
}
~TypeProcessingState() {
if (trivial) return;
restoreDeclSpecAttrs();
}
private:
DeclSpec &getMutableDeclSpec() const {
return const_cast<DeclSpec&>(declarator.getDeclSpec());
}
void restoreDeclSpecAttrs() {
assert(hasSavedAttrs);
if (savedAttrs.empty()) {
getMutableDeclSpec().getAttributes().set(0);
return;
}
getMutableDeclSpec().getAttributes().set(savedAttrs[0]);
for (unsigned i = 0, e = savedAttrs.size() - 1; i != e; ++i)
savedAttrs[i]->setNext(savedAttrs[i+1]);
savedAttrs.back()->setNext(0);
}
};
struct AttrAndList {
AttributeList &first;
AttributeList *&second;
AttrAndList(AttributeList &attr, AttributeList *&head)
: first(attr), second(head) {}
};
}
namespace llvm {
template <> struct isPodLike<AttrAndList> {
static const bool value = true;
};
}
static void spliceAttrIntoList(AttributeList &attr, AttributeList *&head) {
attr.setNext(head);
head = &attr;
}
static void spliceAttrOutOfList(AttributeList &attr, AttributeList *&head) {
if (head == &attr) {
head = attr.getNext();
return;
}
AttributeList *cur = head;
while (true) {
assert(cur && cur->getNext() && "ran out of attrs?");
if (cur->getNext() == &attr) {
cur->setNext(attr.getNext());
return;
}
cur = cur->getNext();
}
}
static void moveAttrFromListToList(AttributeList &attr,
AttributeList *&fromList,
AttributeList *&toList) {
spliceAttrOutOfList(attr, fromList);
spliceAttrIntoList(attr, toList);
}
static void processTypeAttrs(TypeProcessingState &state,
QualType &type, bool isDeclSpec,
AttributeList *attrs);
static bool handleFunctionTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType &type);
static bool handleObjCGCTypeAttr(TypeProcessingState &state,
AttributeList &attr, QualType &type);
static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
AttributeList &attr, QualType &type);
static bool handleObjCPointerTypeAttr(TypeProcessingState &state,
AttributeList &attr, QualType &type) {
if (attr.getKind() == AttributeList::AT_ObjCGC)
return handleObjCGCTypeAttr(state, attr, type);
assert(attr.getKind() == AttributeList::AT_ObjCOwnership);
return handleObjCOwnershipTypeAttr(state, attr, type);
}
static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType type) {
Declarator &declarator = state.getDeclarator();
for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
switch (chunk.Kind) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
chunk.getAttrListRef());
return;
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
continue;
case DeclaratorChunk::Reference:
case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
goto error;
}
}
error:
diagnoseBadTypeAttribute(state.getSema(), attr, type);
}
static void
distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
AttributeList &attr,
QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
unsigned innermost = -1U;
bool considerDeclSpec = true;
for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i);
switch (chunk.Kind) {
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
innermost = i;
continue;
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
case DeclaratorChunk::Paren:
case DeclaratorChunk::Array:
continue;
case DeclaratorChunk::Function:
considerDeclSpec = false;
goto done;
}
}
done:
if (considerDeclSpec) {
if (handleObjCPointerTypeAttr(state, attr, declSpecType)) {
state.saveDeclSpecAttrs();
moveAttrFromListToList(attr, declarator.getAttrListRef(),
declarator.getMutableDeclSpec().getAttributes().getListRef());
return;
}
}
if (innermost != -1U) {
moveAttrFromListToList(attr, declarator.getAttrListRef(),
declarator.getTypeObject(innermost).getAttrListRef());
return;
}
spliceAttrOutOfList(attr, declarator.getAttrListRef());
state.addIgnoredTypeAttr(attr);
}
static void distributeFunctionTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType type) {
Declarator &declarator = state.getDeclarator();
for (unsigned i = state.getCurrentChunkIndex(); i != 0; --i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i-1);
switch (chunk.Kind) {
case DeclaratorChunk::Function:
moveAttrFromListToList(attr, state.getCurrentAttrListRef(),
chunk.getAttrListRef());
return;
case DeclaratorChunk::Paren:
case DeclaratorChunk::Pointer:
case DeclaratorChunk::BlockPointer:
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
continue;
}
}
diagnoseBadTypeAttribute(state.getSema(), attr, type);
}
static bool
distributeFunctionTypeAttrToInnermost(TypeProcessingState &state,
AttributeList &attr,
AttributeList *&attrList,
QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = declarator.getTypeObject(i);
if (chunk.Kind != DeclaratorChunk::Function) continue;
moveAttrFromListToList(attr, attrList, chunk.getAttrListRef());
return true;
}
if (handleFunctionTypeAttr(state, attr, declSpecType)) {
spliceAttrOutOfList(attr, attrList);
return true;
}
return false;
}
static void
distributeFunctionTypeAttrFromDeclSpec(TypeProcessingState &state,
AttributeList &attr,
QualType &declSpecType) {
state.saveDeclSpecAttrs();
if (distributeFunctionTypeAttrToInnermost(state, attr,
state.getCurrentAttrListRef(),
declSpecType))
return;
state.addIgnoredTypeAttr(attr);
}
static void
distributeFunctionTypeAttrFromDeclarator(TypeProcessingState &state,
AttributeList &attr,
QualType &declSpecType) {
Declarator &declarator = state.getDeclarator();
if (distributeFunctionTypeAttrToInnermost(state, attr,
declarator.getAttrListRef(),
declSpecType))
return;
spliceAttrOutOfList(attr, declarator.getAttrListRef());
state.addIgnoredTypeAttr(attr);
}
static void distributeTypeAttrsFromDeclarator(TypeProcessingState &state,
QualType &declSpecType) {
assert(state.getDeclarator().getAttributes() && "declarator has no attrs!");
AttributeList *attr = state.getDeclarator().getAttributes();
AttributeList *next;
do {
next = attr->getNext();
switch (attr->getKind()) {
OBJC_POINTER_TYPE_ATTRS_CASELIST:
distributeObjCPointerTypeAttrFromDeclarator(state, *attr, declSpecType);
break;
case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
break;
FUNCTION_TYPE_ATTRS_CASELIST:
distributeFunctionTypeAttrFromDeclarator(state, *attr, declSpecType);
break;
default:
break;
}
} while ((attr = next));
}
static void maybeSynthesizeBlockSignature(TypeProcessingState &state,
QualType declSpecType) {
Declarator &declarator = state.getDeclarator();
if (declarator.isFunctionDeclarator()) {
declarator.getFunctionTypeInfo().hasPrototype = true;
return;
}
if (!declarator.getNumTypeObjects() && declSpecType->isFunctionType())
return;
SourceLocation loc = declarator.getLocStart();
declarator.AddInnermostTypeInfo(DeclaratorChunk::getFunction(
true,
false,
false, SourceLocation(),
0, 0,
0,
true, SourceLocation(),
SourceLocation(),
SourceLocation(),
SourceLocation(),
EST_None, SourceLocation(), 0, 0, 0, 0,
loc, loc,
declarator));
assert(state.getCurrentChunkIndex() == declarator.getNumTypeObjects() - 1);
state.setCurrentChunkIndex(declarator.getNumTypeObjects());
}
static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
Sema &S = state.getSema();
Declarator &declarator = state.getDeclarator();
const DeclSpec &DS = declarator.getDeclSpec();
SourceLocation DeclLoc = declarator.getIdentifierLoc();
if (DeclLoc.isInvalid())
DeclLoc = DS.getLocStart();
ASTContext &Context = S.Context;
QualType Result;
switch (DS.getTypeSpecType()) {
case DeclSpec::TST_void:
Result = Context.VoidTy;
break;
case DeclSpec::TST_char:
if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
Result = Context.CharTy;
else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed)
Result = Context.SignedCharTy;
else {
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
"Unknown TSS value");
Result = Context.UnsignedCharTy;
}
break;
case DeclSpec::TST_wchar:
if (DS.getTypeSpecSign() == DeclSpec::TSS_unspecified)
Result = Context.WCharTy;
else if (DS.getTypeSpecSign() == DeclSpec::TSS_signed) {
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
<< DS.getSpecifierName(DS.getTypeSpecType());
Result = Context.getSignedWCharType();
} else {
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unsigned &&
"Unknown TSS value");
S.Diag(DS.getTypeSpecSignLoc(), diag::ext_invalid_sign_spec)
<< DS.getSpecifierName(DS.getTypeSpecType());
Result = Context.getUnsignedWCharType();
}
break;
case DeclSpec::TST_char16:
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
"Unknown TSS value");
Result = Context.Char16Ty;
break;
case DeclSpec::TST_char32:
assert(DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
"Unknown TSS value");
Result = Context.Char32Ty;
break;
case DeclSpec::TST_unspecified:
if (DeclSpec::ProtocolQualifierListTy PQ = DS.getProtocolQualifiers()) {
Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
(ObjCProtocolDecl*const*)PQ,
DS.getNumProtocolQualifiers());
Result = Context.getObjCObjectPointerType(Result);
break;
}
if (declarator.getContext() == Declarator::LambdaExprContext ||
isOmittedBlockReturnType(declarator)) {
Result = Context.DependentTy;
break;
}
if (S.getLangOpts().ImplicitInt) {
if (DS.isEmpty()) {
S.Diag(DeclLoc, diag::ext_missing_declspec)
<< DS.getSourceRange()
<< FixItHint::CreateInsertion(DS.getLocStart(), "int");
}
} else if (!DS.hasTypeSpecifier()) {
if (S.getLangOpts().CPlusPlus &&
!S.getLangOpts().MicrosoftExt) {
S.Diag(DeclLoc, diag::err_missing_type_specifier)
<< DS.getSourceRange();
declarator.setInvalidType(true);
} else {
S.Diag(DeclLoc, diag::ext_missing_type_specifier)
<< DS.getSourceRange();
}
}
case DeclSpec::TST_int: {
if (DS.getTypeSpecSign() != DeclSpec::TSS_unsigned) {
switch (DS.getTypeSpecWidth()) {
case DeclSpec::TSW_unspecified: Result = Context.IntTy; break;
case DeclSpec::TSW_short: Result = Context.ShortTy; break;
case DeclSpec::TSW_long: Result = Context.LongTy; break;
case DeclSpec::TSW_longlong:
Result = Context.LongLongTy;
if (!S.getLangOpts().C99) {
if (S.getLangOpts().CPlusPlus)
S.Diag(DS.getTypeSpecWidthLoc(),
S.getLangOpts().CPlusPlus0x ?
diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
else
S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong);
}
break;
}
} else {
switch (DS.getTypeSpecWidth()) {
case DeclSpec::TSW_unspecified: Result = Context.UnsignedIntTy; break;
case DeclSpec::TSW_short: Result = Context.UnsignedShortTy; break;
case DeclSpec::TSW_long: Result = Context.UnsignedLongTy; break;
case DeclSpec::TSW_longlong:
Result = Context.UnsignedLongLongTy;
if (!S.getLangOpts().C99) {
if (S.getLangOpts().CPlusPlus)
S.Diag(DS.getTypeSpecWidthLoc(),
S.getLangOpts().CPlusPlus0x ?
diag::warn_cxx98_compat_longlong : diag::ext_cxx11_longlong);
else
S.Diag(DS.getTypeSpecWidthLoc(), diag::ext_c99_longlong);
}
break;
}
}
break;
}
case DeclSpec::TST_int128:
if (!S.PP.getTargetInfo().hasInt128Type())
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_int128_unsupported);
if (DS.getTypeSpecSign() == DeclSpec::TSS_unsigned)
Result = Context.UnsignedInt128Ty;
else
Result = Context.Int128Ty;
break;
case DeclSpec::TST_half: Result = Context.HalfTy; break;
case DeclSpec::TST_float: Result = Context.FloatTy; break;
case DeclSpec::TST_double:
if (DS.getTypeSpecWidth() == DeclSpec::TSW_long)
Result = Context.LongDoubleTy;
else
Result = Context.DoubleTy;
if (S.getLangOpts().OpenCL && !S.getOpenCLOptions().cl_khr_fp64) {
S.Diag(DS.getTypeSpecTypeLoc(), diag::err_double_requires_fp64);
declarator.setInvalidType(true);
}
break;
case DeclSpec::TST_bool: Result = Context.BoolTy; break; case DeclSpec::TST_decimal32: case DeclSpec::TST_decimal64: case DeclSpec::TST_decimal128: S.Diag(DS.getTypeSpecTypeLoc(), diag::err_decimal_unsupported);
Result = Context.IntTy;
declarator.setInvalidType(true);
break;
case DeclSpec::TST_class:
case DeclSpec::TST_enum:
case DeclSpec::TST_union:
case DeclSpec::TST_struct:
case DeclSpec::TST_interface: {
TypeDecl *D = dyn_cast_or_null<TypeDecl>(DS.getRepAsDecl());
if (!D) {
Result = Context.IntTy;
declarator.setInvalidType(true);
break;
}
S.DiagnoseUseOfDecl(D, DS.getTypeSpecTypeNameLoc());
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 && "No qualifiers on tag names!");
Result = Context.getTypeDeclType(D);
ElaboratedTypeKeyword Keyword
= ElaboratedType::getKeywordForTypeSpec(DS.getTypeSpecType());
Result = S.getElaboratedType(Keyword, DS.getTypeSpecScope(), Result);
break;
}
case DeclSpec::TST_typename: {
assert(DS.getTypeSpecWidth() == 0 && DS.getTypeSpecComplex() == 0 &&
DS.getTypeSpecSign() == 0 &&
"Can't handle qualifiers on typedef names yet!");
Result = S.GetTypeFromParser(DS.getRepAsType());
if (Result.isNull())
declarator.setInvalidType(true);
else if (DeclSpec::ProtocolQualifierListTy PQ
= DS.getProtocolQualifiers()) {
if (const ObjCObjectType *ObjT = Result->getAs<ObjCObjectType>()) {
if (ObjT->getNumProtocols())
Result = ObjT->getBaseType();
if (DS.getNumProtocolQualifiers())
Result = Context.getObjCObjectType(Result,
(ObjCProtocolDecl*const*) PQ,
DS.getNumProtocolQualifiers());
} else if (Result->isObjCIdType()) {
Result = Context.getObjCObjectType(Context.ObjCBuiltinIdTy,
(ObjCProtocolDecl*const*) PQ,
DS.getNumProtocolQualifiers());
Result = Context.getObjCObjectPointerType(Result);
} else if (Result->isObjCClassType()) {
Result = Context.getObjCObjectType(Context.ObjCBuiltinClassTy,
(ObjCProtocolDecl*const*) PQ,
DS.getNumProtocolQualifiers());
Result = Context.getObjCObjectPointerType(Result);
} else {
S.Diag(DeclLoc, diag::err_invalid_protocol_qualifiers)
<< DS.getSourceRange();
declarator.setInvalidType(true);
}
}
break;
}
case DeclSpec::TST_typeofType:
Result = S.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for typeof?");
if (!Result->isDependentType())
if (const TagType *TT = Result->getAs<TagType>())
S.DiagnoseUseOfDecl(TT->getDecl(), DS.getTypeSpecTypeLoc());
Result = Context.getTypeOfType(Result);
break;
case DeclSpec::TST_typeofExpr: {
Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for typeof?");
Result = S.BuildTypeofExprType(E, DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
break;
}
case DeclSpec::TST_decltype: {
Expr *E = DS.getRepAsExpr();
assert(E && "Didn't get an expression for decltype?");
Result = S.BuildDecltypeType(E, DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
break;
}
case DeclSpec::TST_underlyingType:
Result = S.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for __underlying_type?");
Result = S.BuildUnaryTransformType(Result,
UnaryTransformType::EnumUnderlyingType,
DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
break;
case DeclSpec::TST_auto: {
Result = Context.getAutoType(QualType());
break;
}
case DeclSpec::TST_unknown_anytype:
Result = Context.UnknownAnyTy;
break;
case DeclSpec::TST_atomic:
Result = S.GetTypeFromParser(DS.getRepAsType());
assert(!Result.isNull() && "Didn't get a type for _Atomic?");
Result = S.BuildAtomicType(Result, DS.getTypeSpecTypeLoc());
if (Result.isNull()) {
Result = Context.IntTy;
declarator.setInvalidType(true);
}
break;
case DeclSpec::TST_error:
Result = Context.IntTy;
declarator.setInvalidType(true);
break;
}
if (DS.getTypeSpecComplex() == DeclSpec::TSC_complex) {
if (S.getLangOpts().Freestanding)
S.Diag(DS.getTypeSpecComplexLoc(), diag::ext_freestanding_complex);
Result = Context.getComplexType(Result);
} else if (DS.isTypeAltiVecVector()) {
unsigned typeSize = static_cast<unsigned>(Context.getTypeSize(Result));
assert(typeSize > 0 && "type size for vector must be greater than 0 bits");
VectorType::VectorKind VecKind = VectorType::AltiVecVector;
if (DS.isTypeAltiVecPixel())
VecKind = VectorType::AltiVecPixel;
else if (DS.isTypeAltiVecBool())
VecKind = VectorType::AltiVecBool;
Result = Context.getVectorType(Result, 128/typeSize, VecKind);
}
if (DS.getTypeSpecComplex() == DeclSpec::TSC_imaginary)
S.Diag(DS.getTypeSpecComplexLoc(), diag::err_imaginary_not_supported);
if (declarator.getContext() == Declarator::BlockLiteralContext)
maybeSynthesizeBlockSignature(state, Result);
if (AttributeList *attrs = DS.getAttributes().getList())
processTypeAttrs(state, Result, true, attrs);
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
if (TypeQuals & DeclSpec::TQ_restrict) {
if (Result->isAnyPointerType() || Result->isReferenceType()) {
QualType EltTy;
if (Result->isObjCObjectPointerType())
EltTy = Result;
else
EltTy = Result->isPointerType() ?
Result->getAs<PointerType>()->getPointeeType() :
Result->getAs<ReferenceType>()->getPointeeType();
if (!EltTy->isIncompleteOrObjectType()) {
S.Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_invalid_pointee)
<< EltTy << DS.getSourceRange();
TypeQuals &= ~DeclSpec::TQ_restrict; }
} else {
S.Diag(DS.getRestrictSpecLoc(),
diag::err_typecheck_invalid_restrict_not_pointer)
<< Result << DS.getSourceRange();
TypeQuals &= ~DeclSpec::TQ_restrict; }
}
if (Result->isFunctionType() && TypeQuals) {
SourceLocation Loc;
if (TypeQuals & DeclSpec::TQ_const)
Loc = DS.getConstSpecLoc();
else if (TypeQuals & DeclSpec::TQ_volatile)
Loc = DS.getVolatileSpecLoc();
else {
assert((TypeQuals & DeclSpec::TQ_restrict) &&
"Has CVR quals but not C, V, or R?");
Loc = DS.getRestrictSpecLoc();
}
S.Diag(Loc, diag::warn_typecheck_function_qualifiers)
<< Result << DS.getSourceRange();
}
if (DS.getTypeSpecType() == DeclSpec::TST_typename &&
TypeQuals && Result->isReferenceType()) {
TypeQuals &= ~DeclSpec::TQ_const;
TypeQuals &= ~DeclSpec::TQ_volatile;
}
if (!S.getLangOpts().C99 && !S.getLangOpts().CPlusPlus
&& TypeQuals & Result.getCVRQualifiers()) {
if (TypeQuals & DeclSpec::TQ_const && Result.isConstQualified()) {
S.Diag(DS.getConstSpecLoc(), diag::ext_duplicate_declspec)
<< "const";
}
if (TypeQuals & DeclSpec::TQ_volatile && Result.isVolatileQualified()) {
S.Diag(DS.getVolatileSpecLoc(), diag::ext_duplicate_declspec)
<< "volatile";
}
}
Qualifiers Quals = Qualifiers::fromCVRMask(TypeQuals);
Result = Context.getQualifiedType(Result, Quals);
}
return Result;
}
static std::string getPrintableNameForEntity(DeclarationName Entity) {
if (Entity)
return Entity.getAsString();
return "type name";
}
QualType Sema::BuildQualifiedType(QualType T, SourceLocation Loc,
Qualifiers Qs) {
if (Qs.hasRestrict()) {
unsigned DiagID = 0;
QualType ProblemTy;
const Type *Ty = T->getCanonicalTypeInternal().getTypePtr();
if (const ReferenceType *RTy = dyn_cast<ReferenceType>(Ty)) {
if (!RTy->getPointeeType()->isIncompleteOrObjectType()) {
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
ProblemTy = T->getAs<ReferenceType>()->getPointeeType();
}
} else if (const PointerType *PTy = dyn_cast<PointerType>(Ty)) {
if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
ProblemTy = T->getAs<PointerType>()->getPointeeType();
}
} else if (const MemberPointerType *PTy = dyn_cast<MemberPointerType>(Ty)) {
if (!PTy->getPointeeType()->isIncompleteOrObjectType()) {
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
ProblemTy = T->getAs<PointerType>()->getPointeeType();
}
} else if (!Ty->isDependentType()) {
DiagID = diag::err_typecheck_invalid_restrict_invalid_pointee;
ProblemTy = T;
}
if (DiagID) {
Diag(Loc, DiagID) << ProblemTy;
Qs.removeRestrict();
}
}
return Context.getQualifiedType(T, Qs);
}
QualType Sema::BuildParenType(QualType T) {
return Context.getParenType(T);
}
static QualType inferARCLifetimeForPointee(Sema &S, QualType type,
SourceLocation loc,
bool isReference) {
if (!type->isObjCLifetimeType() ||
type.getObjCLifetime() != Qualifiers::OCL_None)
return type;
Qualifiers::ObjCLifetime implicitLifetime = Qualifiers::OCL_None;
if (type.isConstQualified()) {
implicitLifetime = Qualifiers::OCL_ExplicitNone;
} else if (type->isObjCARCImplicitlyUnretainedType()) {
implicitLifetime = Qualifiers::OCL_ExplicitNone;
} else if (S.isUnevaluatedContext()) {
return type;
} else {
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
sema::DelayedDiagnostic::makeForbiddenType(loc,
diag::err_arc_indirect_no_ownership, type, isReference));
} else {
S.Diag(loc, diag::err_arc_indirect_no_ownership) << type << isReference;
}
implicitLifetime = Qualifiers::OCL_Strong;
}
assert(implicitLifetime && "didn't infer any lifetime!");
Qualifiers qs;
qs.addObjCLifetime(implicitLifetime);
return S.Context.getQualifiedType(type, qs);
}
QualType Sema::BuildPointerType(QualType T,
SourceLocation Loc, DeclarationName Entity) {
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_pointer_to_reference)
<< getPrintableNameForEntity(Entity) << T;
return QualType();
}
assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
if (getLangOpts().ObjCAutoRefCount)
T = inferARCLifetimeForPointee(*this, T, Loc, false);
return Context.getPointerType(T);
}
QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
SourceLocation Loc,
DeclarationName Entity) {
assert(Context.getCanonicalType(T) != Context.OverloadTy &&
"Unresolved overloaded function type");
bool LValueRef = SpelledAsLValue || T->getAs<LValueReferenceType>();
if (T->isVoidType()) {
Diag(Loc, diag::err_reference_to_void);
return QualType();
}
if (getLangOpts().ObjCAutoRefCount)
T = inferARCLifetimeForPointee(*this, T, Loc, true);
if (LValueRef)
return Context.getLValueReferenceType(T, SpelledAsLValue);
return Context.getRValueReferenceType(T);
}
static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
class VLADiagnoser : public Sema::VerifyICEDiagnoser {
public:
VLADiagnoser() : Sema::VerifyICEDiagnoser(true) {}
virtual void diagnoseNotICE(Sema &S, SourceLocation Loc, SourceRange SR) {
}
virtual void diagnoseFold(Sema &S, SourceLocation Loc, SourceRange SR) {
S.Diag(Loc, diag::ext_vla_folded_to_constant) << SR;
}
} Diagnoser;
return S.VerifyIntegerConstantExpression(ArraySize, &SizeVal, Diagnoser,
S.LangOpts.GNUMode).isInvalid();
}
QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
Expr *ArraySize, unsigned Quals,
SourceRange Brackets, DeclarationName Entity) {
SourceLocation Loc = Brackets.getBegin();
if (getLangOpts().CPlusPlus) {
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_array_of_references)
<< getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (T->isVoidType() || T->isIncompleteArrayType()) {
Diag(Loc, diag::err_illegal_decl_array_incomplete_type) << T;
return QualType();
}
if (RequireNonAbstractType(Brackets.getBegin(), T,
diag::err_array_of_abstract_type))
return QualType();
} else {
if (RequireCompleteType(Loc, T,
diag::err_illegal_decl_array_incomplete_type))
return QualType();
}
if (T->isFunctionType()) {
Diag(Loc, diag::err_illegal_decl_array_of_functions)
<< getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (T->getContainedAutoType()) {
Diag(Loc, diag::err_illegal_decl_array_of_auto)
<< getPrintableNameForEntity(Entity) << T;
return QualType();
}
if (const RecordType *EltTy = T->getAs<RecordType>()) {
if (EltTy->getDecl()->hasFlexibleArrayMember())
Diag(Loc, diag::ext_flexible_array_in_array) << T;
} else if (T->isObjCObjectType()) {
Diag(Loc, diag::err_objc_array_of_interfaces) << T;
return QualType();
}
if (ArraySize && ArraySize->hasPlaceholderType()) {
ExprResult Result = CheckPlaceholderExpr(ArraySize);
if (Result.isInvalid()) return QualType();
ArraySize = Result.take();
}
if (ArraySize && !ArraySize->isRValue()) {
ExprResult Result = DefaultLvalueConversion(ArraySize);
if (Result.isInvalid())
return QualType();
ArraySize = Result.take();
}
if (!getLangOpts().CPlusPlus0x &&
ArraySize && !ArraySize->isTypeDependent() &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
<< ArraySize->getType() << ArraySize->getSourceRange();
return QualType();
}
llvm::APSInt ConstVal(Context.getTypeSize(Context.getSizeType()));
if (!ArraySize) {
if (ASM == ArrayType::Star)
T = Context.getVariableArrayType(T, 0, ASM, Quals, Brackets);
else
T = Context.getIncompleteArrayType(T, ASM, Quals);
} else if (ArraySize->isTypeDependent() || ArraySize->isValueDependent()) {
T = Context.getDependentSizedArrayType(T, ArraySize, ASM, Quals, Brackets);
} else if ((!T->isDependentType() && !T->isIncompleteType() &&
!T->isConstantSizeType()) ||
isArraySizeVLA(*this, ArraySize, ConstVal)) {
if (getLangOpts().CPlusPlus0x &&
!ArraySize->getType()->isIntegralOrUnscopedEnumerationType()) {
Diag(ArraySize->getLocStart(), diag::err_array_size_non_int)
<< ArraySize->getType() << ArraySize->getSourceRange();
return QualType();
}
T = Context.getVariableArrayType(T, ArraySize, ASM, Quals, Brackets);
} else {
if (ConstVal.isSigned() && ConstVal.isNegative()) {
if (Entity)
Diag(ArraySize->getLocStart(), diag::err_decl_negative_array_size)
<< getPrintableNameForEntity(Entity) << ArraySize->getSourceRange();
else
Diag(ArraySize->getLocStart(), diag::err_typecheck_negative_array_size)
<< ArraySize->getSourceRange();
return QualType();
}
if (ConstVal == 0) {
Diag(ArraySize->getLocStart(),
isSFINAEContext()? diag::err_typecheck_zero_array_size
: diag::ext_typecheck_zero_array_size)
<< ArraySize->getSourceRange();
if (ASM == ArrayType::Static) {
Diag(ArraySize->getLocStart(),
diag::warn_typecheck_zero_static_array_size)
<< ArraySize->getSourceRange();
ASM = ArrayType::Normal;
}
} else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
!T->isIncompleteType()) {
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 (!getLangOpts().C99) {
if (T->isVariableArrayType()) {
QualType BaseT = Context.getBaseElementType(T);
if (!T->isDependentType() &&
!BaseT.isPODType(Context) &&
!BaseT->isObjCLifetimeType()) {
Diag(Loc, diag::err_vla_non_pod)
<< BaseT;
return QualType();
}
else if (isSFINAEContext()) {
Diag(Loc, diag::err_vla_in_sfinae);
return QualType();
}
else
Diag(Loc, diag::ext_vla);
} else if (ASM != ArrayType::Normal || Quals != 0)
Diag(Loc,
getLangOpts().CPlusPlus? diag::err_c99_array_usage_cxx
: diag::ext_c99_array_usage) << ASM;
}
return T;
}
QualType Sema::BuildExtVectorType(QualType T, Expr *ArraySize,
SourceLocation AttrLoc) {
if (!T->isDependentType() &&
!T->isIntegerType() && !T->isRealFloatingType()) {
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << T;
return QualType();
}
if (!ArraySize->isTypeDependent() && !ArraySize->isValueDependent()) {
llvm::APSInt vecSize(32);
if (!ArraySize->isIntegerConstantExpr(vecSize, Context)) {
Diag(AttrLoc, diag::err_attribute_argument_not_int)
<< "ext_vector_type" << ArraySize->getSourceRange();
return QualType();
}
unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue());
if (vectorSize == 0) {
Diag(AttrLoc, diag::err_attribute_zero_size)
<< ArraySize->getSourceRange();
return QualType();
}
return Context.getExtVectorType(T, vectorSize);
}
return Context.getDependentSizedExtVectorType(T, ArraySize, AttrLoc);
}
QualType Sema::BuildFunctionType(QualType T,
QualType *ParamTypes,
unsigned NumParamTypes,
bool Variadic, bool HasTrailingReturn,
unsigned Quals,
RefQualifierKind RefQualifier,
SourceLocation Loc, DeclarationName Entity,
FunctionType::ExtInfo Info) {
if (T->isArrayType() || T->isFunctionType()) {
Diag(Loc, diag::err_func_returning_array_function)
<< T->isFunctionType() << T;
return QualType();
}
if (T->isHalfType()) {
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 1 <<
FixItHint::CreateInsertion(Loc, "*");
return QualType();
}
bool Invalid = false;
for (unsigned Idx = 0; Idx < NumParamTypes; ++Idx) {
QualType ParamType = Context.getAdjustedParameterType(ParamTypes[Idx]);
if (ParamType->isVoidType()) {
Diag(Loc, diag::err_param_with_void_type);
Invalid = true;
} else if (ParamType->isHalfType()) {
Diag(Loc, diag::err_parameters_retval_cannot_have_fp16_type) << 0 <<
FixItHint::CreateInsertion(Loc, "*");
Invalid = true;
}
ParamTypes[Idx] = ParamType;
}
if (Invalid)
return QualType();
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = Variadic;
EPI.HasTrailingReturn = HasTrailingReturn;
EPI.TypeQuals = Quals;
EPI.RefQualifier = RefQualifier;
EPI.ExtInfo = Info;
return Context.getFunctionType(T, ParamTypes, NumParamTypes, EPI);
}
QualType Sema::BuildMemberPointerType(QualType T, QualType Class,
SourceLocation Loc,
DeclarationName Entity) {
if (CheckDistantExceptionSpec(T)) {
Diag(Loc, diag::err_distant_exception_spec);
T = Context.getCanonicalType(T);
}
if (T->isReferenceType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_reference)
<< (Entity? Entity.getAsString() : "type name") << T;
return QualType();
}
if (T->isVoidType()) {
Diag(Loc, diag::err_illegal_decl_mempointer_to_void)
<< (Entity? Entity.getAsString() : "type name");
return QualType();
}
if (!Class->isDependentType() && !Class->isRecordType()) {
Diag(Loc, diag::err_mempointer_in_nonclass_type) << Class;
return QualType();
}
if (Context.getTargetInfo().getCXXABI() == CXXABI_Microsoft &&
RequireCompleteType(Loc, Class, diag::err_incomplete_type))
return QualType();
return Context.getMemberPointerType(T, Class.getTypePtr());
}
QualType Sema::BuildBlockPointerType(QualType T,
SourceLocation Loc,
DeclarationName Entity) {
if (!T->isFunctionType()) {
Diag(Loc, diag::err_nonfunction_block_type);
return QualType();
}
return Context.getBlockPointerType(T);
}
QualType Sema::GetTypeFromParser(ParsedType Ty, TypeSourceInfo **TInfo) {
QualType QT = Ty.get();
if (QT.isNull()) {
if (TInfo) *TInfo = 0;
return QualType();
}
TypeSourceInfo *DI = 0;
if (const LocInfoType *LIT = dyn_cast<LocInfoType>(QT)) {
QT = LIT->getType();
DI = LIT->getTypeSourceInfo();
}
if (TInfo) *TInfo = DI;
return QT;
}
static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
Qualifiers::ObjCLifetime ownership,
unsigned chunkIndex);
static void inferARCWriteback(TypeProcessingState &state,
QualType &declSpecType) {
Sema &S = state.getSema();
Declarator &declarator = state.getDeclarator();
unsigned outermostPointerIndex = 0;
bool isBlockPointer = false;
unsigned numPointers = 0;
for (unsigned i = 0, e = declarator.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = i;
DeclaratorChunk &chunk = declarator.getTypeObject(chunkIndex);
switch (chunk.Kind) {
case DeclaratorChunk::Paren:
break;
case DeclaratorChunk::Reference:
case DeclaratorChunk::Pointer:
outermostPointerIndex = chunkIndex;
numPointers++;
break;
case DeclaratorChunk::BlockPointer:
if (numPointers != 1) return;
numPointers++;
outermostPointerIndex = chunkIndex;
isBlockPointer = true;
goto done;
case DeclaratorChunk::Array: case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
return;
}
}
done:
if (numPointers == 1) {
if (!declSpecType->isObjCRetainableType()) return;
if (declSpecType.getObjCLifetime()) return;
Qualifiers qs;
if (declSpecType->isObjCARCImplicitlyUnretainedType())
qs.addObjCLifetime(Qualifiers::OCL_ExplicitNone);
else
qs.addObjCLifetime(Qualifiers::OCL_Autoreleasing);
declSpecType = S.Context.getQualifiedType(declSpecType, qs);
} else if (numPointers == 2) {
if (!isBlockPointer && !declSpecType->isObjCObjectType())
return;
DeclaratorChunk &chunk = declarator.getTypeObject(outermostPointerIndex);
if (chunk.Kind != DeclaratorChunk::Pointer &&
chunk.Kind != DeclaratorChunk::BlockPointer)
return;
for (const AttributeList *attr = chunk.getAttrs(); attr;
attr = attr->getNext())
if (attr->getKind() == AttributeList::AT_ObjCOwnership)
return;
transferARCOwnershipToDeclaratorChunk(state, Qualifiers::OCL_Autoreleasing,
outermostPointerIndex);
} else return;
}
static void DiagnoseIgnoredQualifiers(unsigned Quals,
SourceLocation ConstQualLoc,
SourceLocation VolatileQualLoc,
SourceLocation RestrictQualLoc,
Sema& S) {
std::string QualStr;
unsigned NumQuals = 0;
SourceLocation Loc;
FixItHint ConstFixIt;
FixItHint VolatileFixIt;
FixItHint RestrictFixIt;
const SourceManager &SM = S.getSourceManager();
if (Quals & Qualifiers::Const) {
ConstFixIt = FixItHint::CreateRemoval(ConstQualLoc);
QualStr = "const";
++NumQuals;
if (!Loc.isValid() || SM.isBeforeInTranslationUnit(ConstQualLoc, Loc))
Loc = ConstQualLoc;
}
if (Quals & Qualifiers::Volatile) {
VolatileFixIt = FixItHint::CreateRemoval(VolatileQualLoc);
QualStr += (NumQuals == 0 ? "volatile" : " volatile");
++NumQuals;
if (!Loc.isValid() || SM.isBeforeInTranslationUnit(VolatileQualLoc, Loc))
Loc = VolatileQualLoc;
}
if (Quals & Qualifiers::Restrict) {
RestrictFixIt = FixItHint::CreateRemoval(RestrictQualLoc);
QualStr += (NumQuals == 0 ? "restrict" : " restrict");
++NumQuals;
if (!Loc.isValid() || SM.isBeforeInTranslationUnit(RestrictQualLoc, Loc))
Loc = RestrictQualLoc;
}
assert(NumQuals > 0 && "No known qualifiers?");
S.Diag(Loc, diag::warn_qual_return_type)
<< QualStr << NumQuals << ConstFixIt << VolatileFixIt << RestrictFixIt;
}
static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
TypeSourceInfo *&ReturnTypeInfo) {
Sema &SemaRef = state.getSema();
Declarator &D = state.getDeclarator();
QualType T;
ReturnTypeInfo = 0;
TagDecl *OwnedTagDecl = 0;
switch (D.getName().getKind()) {
case UnqualifiedId::IK_ImplicitSelfParam:
case UnqualifiedId::IK_OperatorFunctionId:
case UnqualifiedId::IK_Identifier:
case UnqualifiedId::IK_LiteralOperatorId:
case UnqualifiedId::IK_TemplateId:
T = ConvertDeclSpecToType(state);
if (!D.isInvalidType() && D.getDeclSpec().isTypeSpecOwned()) {
OwnedTagDecl = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
OwnedTagDecl->setEmbeddedInDeclarator(true);
}
break;
case UnqualifiedId::IK_ConstructorName:
case UnqualifiedId::IK_ConstructorTemplateId:
case UnqualifiedId::IK_DestructorName:
T = SemaRef.Context.VoidTy;
if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList())
processTypeAttrs(state, T, true, attrs);
break;
case UnqualifiedId::IK_ConversionFunctionId:
T = SemaRef.GetTypeFromParser(D.getName().ConversionFunctionId,
&ReturnTypeInfo);
break;
}
if (D.getAttributes())
distributeTypeAttrsFromDeclarator(state, T);
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
(!SemaRef.getLangOpts().CPlusPlus0x || !D.isFunctionDeclarator())) {
int Error = -1;
switch (D.getContext()) {
case Declarator::KNRTypeListContext:
llvm_unreachable("K&R type lists aren't allowed in C++");
case Declarator::LambdaExprContext:
llvm_unreachable("Can't specify a type specifier in lambda grammar");
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::PrototypeContext:
Error = 0; break;
case Declarator::MemberContext:
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
break;
switch (cast<TagDecl>(SemaRef.CurContext)->getTagKind()) {
case TTK_Enum: llvm_unreachable("unhandled tag kind");
case TTK_Struct: Error = 1; break;
case TTK_Union: Error = 2; break;
case TTK_Class: Error = 3; break;
case TTK_Interface: Error = 4; break;
}
break;
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
Error = 5; break;
case Declarator::TemplateParamContext:
Error = 6; break;
case Declarator::BlockLiteralContext:
Error = 7; break;
case Declarator::TemplateTypeArgContext:
Error = 8; break;
case Declarator::AliasDeclContext:
case Declarator::AliasTemplateContext:
Error = 10; break;
case Declarator::TrailingReturnContext:
Error = 11; break;
case Declarator::TypeNameContext:
Error = 12; break;
case Declarator::FileContext:
case Declarator::BlockContext:
case Declarator::ForContext:
case Declarator::ConditionContext:
case Declarator::CXXNewContext:
break;
}
if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef)
Error = 9;
if (D.isFunctionDeclarator())
Error = 11;
if (SemaRef.getLangOpts().CPlusPlus0x && Error != -1) {
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
if (DeclType.Kind == DeclaratorChunk::Function) {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
if (FTI.hasTrailingReturnType()) {
Error = -1;
break;
}
}
}
}
if (Error != -1) {
SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_auto_not_allowed)
<< Error;
T = SemaRef.Context.IntTy;
D.setInvalidType(true);
} else
SemaRef.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::warn_cxx98_compat_auto_type_specifier);
}
if (SemaRef.getLangOpts().CPlusPlus &&
OwnedTagDecl && OwnedTagDecl->isCompleteDefinition()) {
switch (D.getContext()) {
case Declarator::TrailingReturnContext:
llvm_unreachable("parser should not have allowed this");
break;
case Declarator::FileContext:
case Declarator::MemberContext:
case Declarator::BlockContext:
case Declarator::ForContext:
case Declarator::BlockLiteralContext:
case Declarator::LambdaExprContext:
case Declarator::AliasDeclContext:
break;
case Declarator::AliasTemplateContext:
SemaRef.Diag(OwnedTagDecl->getLocation(),
diag::err_type_defined_in_alias_template)
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
break;
case Declarator::TypeNameContext:
case Declarator::TemplateParamContext:
case Declarator::CXXNewContext:
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
case Declarator::TemplateTypeArgContext:
SemaRef.Diag(OwnedTagDecl->getLocation(),
diag::err_type_defined_in_type_specifier)
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
break;
case Declarator::PrototypeContext:
case Declarator::ObjCParameterContext:
case Declarator::ObjCResultContext:
case Declarator::KNRTypeListContext:
SemaRef.Diag(OwnedTagDecl->getLocation(),
diag::err_type_defined_in_param_type)
<< SemaRef.Context.getTypeDeclType(OwnedTagDecl);
break;
case Declarator::ConditionContext:
SemaRef.Diag(OwnedTagDecl->getLocation(),
diag::err_type_defined_in_condition);
break;
}
}
return T;
}
static std::string getFunctionQualifiersAsString(const FunctionProtoType *FnTy){
std::string Quals =
Qualifiers::fromCVRMask(FnTy->getTypeQuals()).getAsString();
switch (FnTy->getRefQualifier()) {
case RQ_None:
break;
case RQ_LValue:
if (!Quals.empty())
Quals += ' ';
Quals += '&';
break;
case RQ_RValue:
if (!Quals.empty())
Quals += ' ';
Quals += "&&";
break;
}
return Quals;
}
static void checkQualifiedFunction(Sema &S, QualType T,
DeclaratorChunk &DeclType) {
int DiagKind = -1;
switch (DeclType.Kind) {
case DeclaratorChunk::Paren:
case DeclaratorChunk::MemberPointer:
return;
case DeclaratorChunk::Array:
case DeclaratorChunk::Function:
return;
case DeclaratorChunk::BlockPointer:
DiagKind = 0;
break;
case DeclaratorChunk::Pointer:
DiagKind = 1;
break;
case DeclaratorChunk::Reference:
DiagKind = 2;
break;
}
assert(DiagKind != -1);
S.Diag(DeclType.Loc, diag::err_compound_qualified_function_type)
<< DiagKind << isa<FunctionType>(T.IgnoreParens()) << T
<< getFunctionQualifiersAsString(T->castAs<FunctionProtoType>());
}
static void warnAboutAmbiguousFunction(Sema &S, Declarator &D,
DeclaratorChunk &DeclType, QualType RT) {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
assert(FTI.isAmbiguous && "no direct-initializer / function ambiguity");
if (RT->isVoidType())
return;
if (!RT->isRecordType() && FTI.NumArgs > 1)
return;
if (RT->isReferenceType() && FTI.NumArgs != 1)
return;
if (!D.isFunctionDeclarator() ||
D.getFunctionDefinitionKind() != FDK_Declaration ||
!S.CurContext->isFunctionOrMethod() ||
D.getDeclSpec().getStorageClassSpecAsWritten()
!= DeclSpec::SCS_unspecified)
return;
if (D.getContext() == Declarator::ConditionContext)
return;
SourceRange ParenRange(DeclType.Loc, DeclType.EndLoc);
S.Diag(DeclType.Loc,
FTI.NumArgs ? diag::warn_parens_disambiguated_as_function_declaration
: diag::warn_empty_parens_are_function_decl)
<< ParenRange;
if (!D.isFirstDeclarator() && D.getIdentifier()) {
FullSourceLoc Comma(D.getCommaLoc(), S.SourceMgr);
FullSourceLoc Name(D.getIdentifierLoc(), S.SourceMgr);
if (Comma.getFileID() != Name.getFileID() ||
Comma.getSpellingLineNumber() != Name.getSpellingLineNumber()) {
LookupResult Result(S, D.getIdentifier(), SourceLocation(),
Sema::LookupOrdinaryName);
if (S.LookupName(Result, S.getCurScope()))
S.Diag(D.getCommaLoc(), diag::note_empty_parens_function_call)
<< FixItHint::CreateReplacement(D.getCommaLoc(), ";")
<< D.getIdentifier();
}
}
if (FTI.NumArgs > 0) {
SourceRange Range = FTI.ArgInfo[0].Param->getSourceRange();
SourceLocation B = Range.getBegin();
SourceLocation E = S.PP.getLocForEndOfToken(Range.getEnd());
S.Diag(B, diag::note_additional_parens_for_variable_declaration)
<< FixItHint::CreateInsertion(B, "(")
<< FixItHint::CreateInsertion(E, ")");
} else {
const CXXRecordDecl *RD = RT->getAsCXXRecordDecl();
if (RD && RD->hasDefinition() &&
(RD->isEmpty() || RD->hasUserProvidedDefaultConstructor()))
S.Diag(DeclType.Loc, diag::note_empty_parens_default_ctor)
<< FixItHint::CreateRemoval(ParenRange);
else {
std::string Init = S.getFixItZeroInitializerForType(RT);
if (Init.empty() && S.LangOpts.CPlusPlus0x)
Init = "{}";
if (!Init.empty())
S.Diag(DeclType.Loc, diag::note_empty_parens_zero_initialize)
<< FixItHint::CreateReplacement(ParenRange, Init);
}
}
}
static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
QualType declSpecType,
TypeSourceInfo *TInfo) {
QualType T = declSpecType;
Declarator &D = state.getDeclarator();
Sema &S = state.getSema();
ASTContext &Context = S.Context;
const LangOptions &LangOpts = S.getLangOpts();
bool ImplicitlyNoexcept = false;
if (D.getName().getKind() == UnqualifiedId::IK_OperatorFunctionId &&
LangOpts.CPlusPlus0x) {
OverloadedOperatorKind OO = D.getName().OperatorFunctionId.Operator;
if (OO == OO_Delete || OO == OO_Array_Delete)
ImplicitlyNoexcept = true;
}
DeclarationName Name;
if (D.getIdentifier())
Name = D.getIdentifier();
bool IsTypedefName =
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef ||
D.getContext() == Declarator::AliasDeclContext ||
D.getContext() == Declarator::AliasTemplateContext;
bool IsQualifiedFunction = T->isFunctionProtoType() &&
(T->castAs<FunctionProtoType>()->getTypeQuals() != 0 ||
T->castAs<FunctionProtoType>()->getRefQualifier() != RQ_None);
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
unsigned chunkIndex = e - i - 1;
state.setCurrentChunkIndex(chunkIndex);
DeclaratorChunk &DeclType = D.getTypeObject(chunkIndex);
if (IsQualifiedFunction) {
checkQualifiedFunction(S, T, DeclType);
IsQualifiedFunction = DeclType.Kind == DeclaratorChunk::Paren;
}
switch (DeclType.Kind) {
case DeclaratorChunk::Paren:
T = S.BuildParenType(T);
break;
case DeclaratorChunk::BlockPointer:
if (!LangOpts.Blocks)
S.Diag(DeclType.Loc, diag::err_blocks_disable);
T = S.BuildBlockPointerType(T, D.getIdentifierLoc(), Name);
if (DeclType.Cls.TypeQuals)
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Cls.TypeQuals);
break;
case DeclaratorChunk::Pointer:
if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
D.setInvalidType(true);
}
if (LangOpts.ObjC1 && T->getAs<ObjCObjectType>()) {
T = Context.getObjCObjectPointerType(T);
if (DeclType.Ptr.TypeQuals)
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
break;
}
T = S.BuildPointerType(T, DeclType.Loc, Name);
if (DeclType.Ptr.TypeQuals)
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Ptr.TypeQuals);
break;
case DeclaratorChunk::Reference: {
if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
D.setInvalidType(true);
}
T = S.BuildReferenceType(T, DeclType.Ref.LValueRef, DeclType.Loc, Name);
Qualifiers Quals;
if (DeclType.Ref.HasRestrict)
T = S.BuildQualifiedType(T, DeclType.Loc, Qualifiers::Restrict);
break;
}
case DeclaratorChunk::Array: {
if (LangOpts.CPlusPlus && S.CheckDistantExceptionSpec(T)) {
S.Diag(D.getIdentifierLoc(), diag::err_distant_exception_spec);
D.setInvalidType(true);
}
DeclaratorChunk::ArrayTypeInfo &ATI = DeclType.Arr;
Expr *ArraySize = static_cast<Expr*>(ATI.NumElts);
ArrayType::ArraySizeModifier ASM;
if (ATI.isStar)
ASM = ArrayType::Star;
else if (ATI.hasStatic)
ASM = ArrayType::Static;
else
ASM = ArrayType::Normal;
if (ASM == ArrayType::Star && !D.isPrototypeContext()) {
S.Diag(DeclType.Loc, diag::err_array_star_outside_prototype);
ASM = ArrayType::Normal;
D.setInvalidType(true);
}
if (ASM == ArrayType::Static || ATI.TypeQuals) {
if (!(D.isPrototypeContext() ||
D.getContext() == Declarator::KNRTypeListContext)) {
S.Diag(DeclType.Loc, diag::err_array_static_outside_prototype) <<
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
if (ASM == ArrayType::Static)
ASM = ArrayType::Normal;
ATI.TypeQuals = 0;
D.setInvalidType(true);
}
unsigned x = chunkIndex;
while (x != 0) {
x--;
const DeclaratorChunk &DC = D.getTypeObject(x);
switch (DC.Kind) {
case DeclaratorChunk::Paren:
continue;
case DeclaratorChunk::Array:
case DeclaratorChunk::Pointer:
case DeclaratorChunk::Reference:
case DeclaratorChunk::MemberPointer:
S.Diag(DeclType.Loc, diag::err_array_static_not_outermost) <<
(ASM == ArrayType::Static ? "'static'" : "type qualifier");
if (ASM == ArrayType::Static)
ASM = ArrayType::Normal;
ATI.TypeQuals = 0;
D.setInvalidType(true);
break;
case DeclaratorChunk::Function:
case DeclaratorChunk::BlockPointer:
break;
}
}
}
T = S.BuildArrayType(T, ASM, ArraySize, ATI.TypeQuals,
SourceRange(DeclType.Loc, DeclType.EndLoc), Name);
break;
}
case DeclaratorChunk::Function: {
const DeclaratorChunk::FunctionTypeInfo &FTI = DeclType.Fun;
IsQualifiedFunction = FTI.TypeQuals || FTI.hasRefQualifier();
if (!D.isInvalidType()) {
if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto &&
!FTI.hasTrailingReturnType() && chunkIndex == 0) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_auto_missing_trailing_return);
T = Context.IntTy;
D.setInvalidType(true);
} else if (FTI.hasTrailingReturnType()) {
if (isa<ParenType>(T)) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_in_parens)
<< T << D.getDeclSpec().getSourceRange();
D.setInvalidType(true);
} else if (D.getContext() != Declarator::LambdaExprContext &&
(T.hasQualifiers() || !isa<AutoType>(T))) {
S.Diag(D.getDeclSpec().getTypeSpecTypeLoc(),
diag::err_trailing_return_without_auto)
<< T << D.getDeclSpec().getSourceRange();
D.setInvalidType(true);
}
T = S.GetTypeFromParser(FTI.getTrailingReturnType(), &TInfo);
if (T.isNull()) {
T = Context.IntTy;
D.setInvalidType(true);
}
}
}
if ((T->isArrayType() || T->isFunctionType()) &&
(D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId)) {
unsigned diagID = diag::err_func_returning_array_function;
if (chunkIndex == 0 &&
D.getContext() == Declarator::BlockLiteralContext)
diagID = diag::err_block_returning_array_function;
S.Diag(DeclType.Loc, diagID) << T->isFunctionType() << T;
T = Context.IntTy;
D.setInvalidType(true);
}
if (T->isHalfType()) {
S.Diag(D.getIdentifierLoc(),
diag::err_parameters_retval_cannot_have_fp16_type) << 1
<< FixItHint::CreateInsertion(D.getIdentifierLoc(), "*");
D.setInvalidType(true);
}
if (isa<PointerType>(T) && T.getLocalCVRQualifiers() &&
(D.getName().getKind() != UnqualifiedId::IK_ConversionFunctionId) &&
(!LangOpts.CPlusPlus || !T->isDependentType())) {
assert(chunkIndex + 1 < e && "No DeclaratorChunk for the return type?");
DeclaratorChunk ReturnTypeChunk = D.getTypeObject(chunkIndex + 1);
assert(ReturnTypeChunk.Kind == DeclaratorChunk::Pointer);
DeclaratorChunk::PointerTypeInfo &PTI = ReturnTypeChunk.Ptr;
DiagnoseIgnoredQualifiers(PTI.TypeQuals,
SourceLocation::getFromRawEncoding(PTI.ConstQualLoc),
SourceLocation::getFromRawEncoding(PTI.VolatileQualLoc),
SourceLocation::getFromRawEncoding(PTI.RestrictQualLoc),
S);
} else if (T.getCVRQualifiers() && D.getDeclSpec().getTypeQualifiers() &&
(!LangOpts.CPlusPlus ||
(!T->isDependentType() && !T->isRecordType()))) {
DiagnoseIgnoredQualifiers(D.getDeclSpec().getTypeQualifiers(),
D.getDeclSpec().getConstSpecLoc(),
D.getDeclSpec().getVolatileSpecLoc(),
D.getDeclSpec().getRestrictSpecLoc(),
S);
}
if (LangOpts.CPlusPlus && D.getDeclSpec().isTypeSpecOwned()) {
TagDecl *Tag = cast<TagDecl>(D.getDeclSpec().getRepAsDecl());
if (Tag->isCompleteDefinition())
S.Diag(Tag->getLocation(), diag::err_type_defined_in_result_type)
<< Context.getTypeDeclType(Tag);
}
if (IsTypedefName && FTI.getExceptionSpecType())
S.Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef)
<< (D.getContext() == Declarator::AliasDeclContext ||
D.getContext() == Declarator::AliasTemplateContext);
if (FTI.isAmbiguous)
warnAboutAmbiguousFunction(S, D, DeclType, T);
if (!FTI.NumArgs && !FTI.isVariadic && !LangOpts.CPlusPlus) {
T = Context.getFunctionNoProtoType(T);
} else {
if (!FTI.NumArgs && FTI.isVariadic && !LangOpts.CPlusPlus) {
bool Overloadable = false;
for (const AttributeList *Attrs = D.getAttributes();
Attrs; Attrs = Attrs->getNext()) {
if (Attrs->getKind() == AttributeList::AT_Overloadable) {
Overloadable = true;
break;
}
}
if (!Overloadable)
S.Diag(FTI.getEllipsisLoc(), diag::err_ellipsis_first_arg);
}
if (FTI.NumArgs && FTI.ArgInfo[0].Param == 0) {
S.Diag(FTI.ArgInfo[0].IdentLoc, diag::err_ident_list_in_fn_declaration);
D.setInvalidType(true);
break;
}
FunctionProtoType::ExtProtoInfo EPI;
EPI.Variadic = FTI.isVariadic;
EPI.HasTrailingReturn = FTI.hasTrailingReturnType();
EPI.TypeQuals = FTI.TypeQuals;
EPI.RefQualifier = !FTI.hasRefQualifier()? RQ_None
: FTI.RefQualifierIsLValueRef? RQ_LValue
: RQ_RValue;
SmallVector<QualType, 16> ArgTys;
ArgTys.reserve(FTI.NumArgs);
SmallVector<bool, 16> ConsumedArguments;
ConsumedArguments.reserve(FTI.NumArgs);
bool HasAnyConsumedArguments = false;
for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
QualType ArgTy = Param->getType();
assert(!ArgTy.isNull() && "Couldn't parse type?");
assert((ArgTy == Context.getAdjustedParameterType(ArgTy)) &&
"Unadjusted type?");
if (ArgTy->isVoidType()) {
if (FTI.NumArgs != 1 || FTI.isVariadic) {
S.Diag(DeclType.Loc, diag::err_void_only_param);
ArgTy = Context.IntTy;
Param->setType(ArgTy);
} else if (FTI.ArgInfo[i].Ident) {
S.Diag(FTI.ArgInfo[i].IdentLoc,
diag::err_param_with_void_type);
ArgTy = Context.IntTy;
Param->setType(ArgTy);
} else {
if (ArgTy.hasQualifiers())
S.Diag(DeclType.Loc, diag::err_void_param_qualified);
break;
}
} else if (ArgTy->isHalfType()) {
S.Diag(Param->getLocation(),
diag::err_parameters_retval_cannot_have_fp16_type) << 0
<< FixItHint::CreateInsertion(Param->getLocation(), "*");
D.setInvalidType();
} else if (!FTI.hasPrototype) {
if (ArgTy->isPromotableIntegerType()) {
ArgTy = Context.getPromotedIntegerType(ArgTy);
Param->setKNRPromoted(true);
} else if (const BuiltinType* BTy = ArgTy->getAs<BuiltinType>()) {
if (BTy->getKind() == BuiltinType::Float) {
ArgTy = Context.DoubleTy;
Param->setKNRPromoted(true);
}
}
}
if (LangOpts.ObjCAutoRefCount) {
bool Consumed = Param->hasAttr<NSConsumedAttr>();
ConsumedArguments.push_back(Consumed);
HasAnyConsumedArguments |= Consumed;
}
ArgTys.push_back(ArgTy);
}
if (HasAnyConsumedArguments)
EPI.ConsumedArguments = ConsumedArguments.data();
SmallVector<QualType, 4> Exceptions;
SmallVector<ParsedType, 2> DynamicExceptions;
SmallVector<SourceRange, 2> DynamicExceptionRanges;
Expr *NoexceptExpr = 0;
if (FTI.getExceptionSpecType() == EST_Dynamic) {
unsigned N = FTI.NumExceptions;
DynamicExceptions.reserve(N);
DynamicExceptionRanges.reserve(N);
for (unsigned I = 0; I != N; ++I) {
DynamicExceptions.push_back(FTI.Exceptions[I].Ty);
DynamicExceptionRanges.push_back(FTI.Exceptions[I].Range);
}
} else if (FTI.getExceptionSpecType() == EST_ComputedNoexcept) {
NoexceptExpr = FTI.NoexceptExpr;
}
S.checkExceptionSpecification(FTI.getExceptionSpecType(),
DynamicExceptions,
DynamicExceptionRanges,
NoexceptExpr,
Exceptions,
EPI);
if (FTI.getExceptionSpecType() == EST_None &&
ImplicitlyNoexcept && chunkIndex == 0) {
EPI.ExceptionSpecType = EST_BasicNoexcept;
}
T = Context.getFunctionType(T, ArgTys.data(), ArgTys.size(), EPI);
}
break;
}
case DeclaratorChunk::MemberPointer:
CXXScopeSpec &SS = DeclType.Mem.Scope();
QualType ClsType;
if (SS.isInvalid()) {
D.setInvalidType(true);
} else if (S.isDependentScopeSpecifier(SS) ||
dyn_cast_or_null<CXXRecordDecl>(S.computeDeclContext(SS))) {
NestedNameSpecifier *NNS
= static_cast<NestedNameSpecifier*>(SS.getScopeRep());
NestedNameSpecifier *NNSPrefix = NNS->getPrefix();
switch (NNS->getKind()) {
case NestedNameSpecifier::Identifier:
ClsType = Context.getDependentNameType(ETK_None, NNSPrefix,
NNS->getAsIdentifier());
break;
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
llvm_unreachable("Nested-name-specifier must name a type");
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
ClsType = QualType(NNS->getAsType(), 0);
if (NNSPrefix && isa<TemplateSpecializationType>(NNS->getAsType()))
ClsType = Context.getElaboratedType(ETK_None, NNSPrefix, ClsType);
break;
}
} else {
S.Diag(DeclType.Mem.Scope().getBeginLoc(),
diag::err_illegal_decl_mempointer_in_nonclass)
<< (D.getIdentifier() ? D.getIdentifier()->getName() : "type name")
<< DeclType.Mem.Scope().getRange();
D.setInvalidType(true);
}
if (!ClsType.isNull())
T = S.BuildMemberPointerType(T, ClsType, DeclType.Loc, D.getIdentifier());
if (T.isNull()) {
T = Context.IntTy;
D.setInvalidType(true);
} else if (DeclType.Mem.TypeQuals) {
T = S.BuildQualifiedType(T, DeclType.Loc, DeclType.Mem.TypeQuals);
}
break;
}
if (T.isNull()) {
D.setInvalidType(true);
T = Context.IntTy;
}
if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
processTypeAttrs(state, T, false, attrs);
}
if (LangOpts.CPlusPlus && T->isFunctionType()) {
const FunctionProtoType *FnTy = T->getAs<FunctionProtoType>();
assert(FnTy && "Why oh why is there not a FunctionProtoType here?");
bool FreeFunction;
if (!D.getCXXScopeSpec().isSet()) {
FreeFunction = ((D.getContext() != Declarator::MemberContext &&
D.getContext() != Declarator::LambdaExprContext) ||
D.getDeclSpec().isFriendSpecified());
} else {
DeclContext *DC = S.computeDeclContext(D.getCXXScopeSpec());
FreeFunction = (DC && !DC->isRecord());
}
if (D.getDeclSpec().isConstexprSpecified() && !FreeFunction &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static &&
D.getName().getKind() != UnqualifiedId::IK_ConstructorName &&
D.getName().getKind() != UnqualifiedId::IK_ConstructorTemplateId &&
!(FnTy->getTypeQuals() & DeclSpec::TQ_const)) {
FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
EPI.TypeQuals |= DeclSpec::TQ_const;
T = Context.getFunctionType(FnTy->getResultType(),
FnTy->arg_type_begin(),
FnTy->getNumArgs(), EPI);
}
if (IsQualifiedFunction &&
!(!FreeFunction &&
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_static) &&
!IsTypedefName &&
D.getContext() != Declarator::TemplateTypeArgContext) {
SourceLocation Loc = D.getLocStart();
SourceRange RemovalRange;
unsigned I;
if (D.isFunctionDeclarator(I)) {
SmallVector<SourceLocation, 4> RemovalLocs;
const DeclaratorChunk &Chunk = D.getTypeObject(I);
assert(Chunk.Kind == DeclaratorChunk::Function);
if (Chunk.Fun.hasRefQualifier())
RemovalLocs.push_back(Chunk.Fun.getRefQualifierLoc());
if (Chunk.Fun.TypeQuals & Qualifiers::Const)
RemovalLocs.push_back(Chunk.Fun.getConstQualifierLoc());
if (Chunk.Fun.TypeQuals & Qualifiers::Volatile)
RemovalLocs.push_back(Chunk.Fun.getVolatileQualifierLoc());
if (!RemovalLocs.empty()) {
std::sort(RemovalLocs.begin(), RemovalLocs.end(),
BeforeThanCompare<SourceLocation>(S.getSourceManager()));
RemovalRange = SourceRange(RemovalLocs.front(), RemovalLocs.back());
Loc = RemovalLocs.front();
}
}
S.Diag(Loc, diag::err_invalid_qualified_function_type)
<< FreeFunction << D.isFunctionDeclarator() << T
<< getFunctionQualifiersAsString(FnTy)
<< FixItHint::CreateRemoval(RemovalRange);
FunctionProtoType::ExtProtoInfo EPI = FnTy->getExtProtoInfo();
EPI.TypeQuals = 0;
EPI.RefQualifier = RQ_None;
T = Context.getFunctionType(FnTy->getResultType(),
FnTy->arg_type_begin(),
FnTy->getNumArgs(), EPI);
}
}
if (!T.isNull())
if (AttributeList *attrs = D.getAttributes())
processTypeAttrs(state, T, false, attrs);
if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T);
if (D.getDeclSpec().isConstexprSpecified() && T->isObjectType()) {
T.addConst();
}
if (D.hasEllipsis() && !T.isNull()) {
switch (D.getContext()) {
case Declarator::PrototypeContext:
if (!T->containsUnexpandedParameterPack()) {
S.Diag(D.getEllipsisLoc(),
diag::err_function_parameter_pack_without_parameter_packs)
<< T << D.getSourceRange();
D.setEllipsisLoc(SourceLocation());
} else {
T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
}
break;
case Declarator::TemplateParamContext:
if (T->containsUnexpandedParameterPack())
T = Context.getPackExpansionType(T, llvm::Optional<unsigned>());
else
S.Diag(D.getEllipsisLoc(),
LangOpts.CPlusPlus0x
? diag::warn_cxx98_compat_variadic_templates
: diag::ext_variadic_templates);
break;
case Declarator::FileContext:
case Declarator::KNRTypeListContext:
case Declarator::ObjCParameterContext: case Declarator::ObjCResultContext: case Declarator::TypeNameContext:
case Declarator::CXXNewContext:
case Declarator::AliasDeclContext:
case Declarator::AliasTemplateContext:
case Declarator::MemberContext:
case Declarator::BlockContext:
case Declarator::ForContext:
case Declarator::ConditionContext:
case Declarator::CXXCatchContext:
case Declarator::ObjCCatchContext:
case Declarator::BlockLiteralContext:
case Declarator::LambdaExprContext:
case Declarator::TrailingReturnContext:
case Declarator::TemplateTypeArgContext:
S.Diag(D.getEllipsisLoc(), diag::err_ellipsis_in_declarator_not_parameter);
D.setEllipsisLoc(SourceLocation());
break;
}
}
if (T.isNull())
return Context.getNullTypeSourceInfo();
else if (D.isInvalidType())
return Context.getTrivialTypeSourceInfo(T);
return S.GetTypeSourceInfoForDeclarator(D, T, TInfo);
}
TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
TypeProcessingState state(*this, D);
TypeSourceInfo *ReturnTypeInfo = 0;
QualType T = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
if (T.isNull())
return Context.getNullTypeSourceInfo();
if (D.isPrototypeContext() && getLangOpts().ObjCAutoRefCount)
inferARCWriteback(state, T);
return GetFullTypeForDeclarator(state, T, ReturnTypeInfo);
}
static void transferARCOwnershipToDeclSpec(Sema &S,
QualType &declSpecTy,
Qualifiers::ObjCLifetime ownership) {
if (declSpecTy->isObjCRetainableType() &&
declSpecTy.getObjCLifetime() == Qualifiers::OCL_None) {
Qualifiers qs;
qs.addObjCLifetime(ownership);
declSpecTy = S.Context.getQualifiedType(declSpecTy, qs);
}
}
static void transferARCOwnershipToDeclaratorChunk(TypeProcessingState &state,
Qualifiers::ObjCLifetime ownership,
unsigned chunkIndex) {
Sema &S = state.getSema();
Declarator &D = state.getDeclarator();
DeclaratorChunk &chunk = D.getTypeObject(chunkIndex);
for (const AttributeList *attr = chunk.getAttrs(); attr;
attr = attr->getNext())
if (attr->getKind() == AttributeList::AT_ObjCOwnership)
return;
const char *attrStr = 0;
switch (ownership) {
case Qualifiers::OCL_None: llvm_unreachable("no ownership!");
case Qualifiers::OCL_ExplicitNone: attrStr = "none"; break;
case Qualifiers::OCL_Strong: attrStr = "strong"; break;
case Qualifiers::OCL_Weak: attrStr = "weak"; break;
case Qualifiers::OCL_Autoreleasing: attrStr = "autoreleasing"; break;
}
AttributeList *attr = D.getAttributePool()
.create(&S.Context.Idents.get("objc_ownership"), SourceLocation(),
0, SourceLocation(),
&S.Context.Idents.get(attrStr), SourceLocation(),
0, 0, AttributeList::AS_GNU);
spliceAttrIntoList(*attr, chunk.getAttrListRef());
}
static void transferARCOwnership(TypeProcessingState &state,
QualType &declSpecTy,
Qualifiers::ObjCLifetime ownership) {
Sema &S = state.getSema();
Declarator &D = state.getDeclarator();
int inner = -1;
bool hasIndirection = false;
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
DeclaratorChunk &chunk = D.getTypeObject(i);
switch (chunk.Kind) {
case DeclaratorChunk::Paren:
break;
case DeclaratorChunk::Array:
case DeclaratorChunk::Reference:
case DeclaratorChunk::Pointer:
if (inner != -1)
hasIndirection = true;
inner = i;
break;
case DeclaratorChunk::BlockPointer:
if (inner != -1)
transferARCOwnershipToDeclaratorChunk(state, ownership, i);
return;
case DeclaratorChunk::Function:
case DeclaratorChunk::MemberPointer:
return;
}
}
if (inner == -1)
return;
DeclaratorChunk &chunk = D.getTypeObject(inner);
if (chunk.Kind == DeclaratorChunk::Pointer) {
if (declSpecTy->isObjCRetainableType())
return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
if (declSpecTy->isObjCObjectType() && hasIndirection)
return transferARCOwnershipToDeclaratorChunk(state, ownership, inner);
} else {
assert(chunk.Kind == DeclaratorChunk::Array ||
chunk.Kind == DeclaratorChunk::Reference);
return transferARCOwnershipToDeclSpec(S, declSpecTy, ownership);
}
}
TypeSourceInfo *Sema::GetTypeForDeclaratorCast(Declarator &D, QualType FromTy) {
TypeProcessingState state(*this, D);
TypeSourceInfo *ReturnTypeInfo = 0;
QualType declSpecTy = GetDeclSpecTypeForDeclarator(state, ReturnTypeInfo);
if (declSpecTy.isNull())
return Context.getNullTypeSourceInfo();
if (getLangOpts().ObjCAutoRefCount) {
Qualifiers::ObjCLifetime ownership = Context.getInnerObjCOwnership(FromTy);
if (ownership != Qualifiers::OCL_None)
transferARCOwnership(state, declSpecTy, ownership);
}
return GetFullTypeForDeclarator(state, declSpecTy, ReturnTypeInfo);
}
static AttributeList::Kind getAttrListKind(AttributedType::Kind kind) {
switch (kind) {
case AttributedType::attr_address_space:
return AttributeList::AT_AddressSpace;
case AttributedType::attr_regparm:
return AttributeList::AT_Regparm;
case AttributedType::attr_vector_size:
return AttributeList::AT_VectorSize;
case AttributedType::attr_neon_vector_type:
return AttributeList::AT_NeonVectorType;
case AttributedType::attr_neon_polyvector_type:
return AttributeList::AT_NeonPolyVectorType;
case AttributedType::attr_objc_gc:
return AttributeList::AT_ObjCGC;
case AttributedType::attr_objc_ownership:
return AttributeList::AT_ObjCOwnership;
case AttributedType::attr_noreturn:
return AttributeList::AT_NoReturn;
case AttributedType::attr_cdecl:
return AttributeList::AT_CDecl;
case AttributedType::attr_fastcall:
return AttributeList::AT_FastCall;
case AttributedType::attr_stdcall:
return AttributeList::AT_StdCall;
case AttributedType::attr_thiscall:
return AttributeList::AT_ThisCall;
case AttributedType::attr_pascal:
return AttributeList::AT_Pascal;
case AttributedType::attr_pcs:
return AttributeList::AT_Pcs;
}
llvm_unreachable("unexpected attribute kind!");
}
static void fillAttributedTypeLoc(AttributedTypeLoc TL,
const AttributeList *attrs) {
AttributedType::Kind kind = TL.getAttrKind();
assert(attrs && "no type attributes in the expected location!");
AttributeList::Kind parsedKind = getAttrListKind(kind);
while (attrs->getKind() != parsedKind) {
attrs = attrs->getNext();
assert(attrs && "no matching attribute in expected location!");
}
TL.setAttrNameLoc(attrs->getLoc());
if (TL.hasAttrExprOperand())
TL.setAttrExprOperand(attrs->getArg(0));
else if (TL.hasAttrEnumOperand())
TL.setAttrEnumOperandLoc(attrs->getParameterLoc());
if (TL.hasAttrOperand())
TL.setAttrOperandParensRange(SourceRange());
}
namespace {
class TypeSpecLocFiller : public TypeLocVisitor<TypeSpecLocFiller> {
ASTContext &Context;
const DeclSpec &DS;
public:
TypeSpecLocFiller(ASTContext &Context, const DeclSpec &DS)
: Context(Context), DS(DS) {}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, DS.getAttributes().getList());
Visit(TL.getModifiedLoc());
}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
Visit(TL.getUnqualifiedLoc());
}
void VisitTypedefTypeLoc(TypedefTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeLoc());
}
void VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeLoc());
TL.setNameEndLoc(DS.getLocEnd());
}
void VisitObjCObjectTypeLoc(ObjCObjectTypeLoc TL) {
if (DS.getTypeSpecType() == DeclSpec::TST_unspecified) {
TL.setHasBaseTypeAsWritten(false);
TL.getBaseLoc().initialize(Context, SourceLocation());
} else {
TL.setHasBaseTypeAsWritten(true);
Visit(TL.getBaseLoc());
}
if (DS.getProtocolQualifiers()) {
assert(TL.getNumProtocols() > 0);
assert(TL.getNumProtocols() == DS.getNumProtocolQualifiers());
TL.setLAngleLoc(DS.getProtocolLAngleLoc());
TL.setRAngleLoc(DS.getSourceRange().getEnd());
for (unsigned i = 0, e = DS.getNumProtocolQualifiers(); i != e; ++i)
TL.setProtocolLoc(i, DS.getProtocolLocs()[i]);
} else {
assert(TL.getNumProtocols() == 0);
TL.setLAngleLoc(SourceLocation());
TL.setRAngleLoc(SourceLocation());
}
}
void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
TL.setStarLoc(SourceLocation());
Visit(TL.getPointeeLoc());
}
void VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (!TInfo) {
TL.initialize(Context, DS.getTypeSpecTypeNameLoc());
return;
}
TypeLoc OldTL = TInfo->getTypeLoc();
if (TInfo->getType()->getAs<ElaboratedType>()) {
ElaboratedTypeLoc ElabTL = cast<ElaboratedTypeLoc>(OldTL);
TemplateSpecializationTypeLoc NamedTL =
cast<TemplateSpecializationTypeLoc>(ElabTL.getNamedTypeLoc());
TL.copy(NamedTL);
}
else
TL.copy(cast<TemplateSpecializationTypeLoc>(OldTL));
}
void VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofExpr);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
}
void VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_typeofType);
TL.setTypeofLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
void VisitUnaryTransformTypeLoc(UnaryTransformTypeLoc TL) {
assert(DS.getTypeSpecType() == DeclSpec::TST_underlyingType);
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
assert(DS.getRepAsType());
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.setUnderlyingTInfo(TInfo);
}
void VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
TL.setBuiltinLoc(DS.getTypeSpecTypeLoc());
if (TL.needsExtraLocalData()) {
TL.getWrittenBuiltinSpecs() = DS.getWrittenBuiltinSpecs();
if (TL.getWrittenSignSpec() != TSS_unspecified)
TL.setBuiltinLoc(DS.getTypeSpecSignLoc());
else if (TL.getWrittenWidthSpec() != TSW_unspecified)
TL.setBuiltinLoc(DS.getTypeSpecWidthLoc());
}
}
void VisitElaboratedTypeLoc(ElaboratedTypeLoc TL) {
ElaboratedTypeKeyword Keyword
= TypeWithKeyword::getKeywordForTypeSpec(DS.getTypeSpecType());
if (DS.getTypeSpecType() == TST_typename) {
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
if (TInfo) {
TL.copy(cast<ElaboratedTypeLoc>(TInfo->getTypeLoc()));
return;
}
}
TL.setElaboratedKeywordLoc(Keyword != ETK_None
? DS.getTypeSpecTypeLoc()
: SourceLocation());
const CXXScopeSpec& SS = DS.getTypeSpecScope();
TL.setQualifierLoc(SS.getWithLocInContext(Context));
Visit(TL.getNextTypeLoc().getUnqualifiedLoc());
}
void VisitDependentNameTypeLoc(DependentNameTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.copy(cast<DependentNameTypeLoc>(TInfo->getTypeLoc()));
}
void VisitDependentTemplateSpecializationTypeLoc(
DependentTemplateSpecializationTypeLoc TL) {
assert(DS.getTypeSpecType() == TST_typename);
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
assert(TInfo);
TL.copy(cast<DependentTemplateSpecializationTypeLoc>(
TInfo->getTypeLoc()));
}
void VisitTagTypeLoc(TagTypeLoc TL) {
TL.setNameLoc(DS.getTypeSpecTypeNameLoc());
}
void VisitAtomicTypeLoc(AtomicTypeLoc TL) {
TL.setKWLoc(DS.getTypeSpecTypeLoc());
TL.setParensRange(DS.getTypeofParensRange());
TypeSourceInfo *TInfo = 0;
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
}
void VisitTypeLoc(TypeLoc TL) {
TL.initialize(Context, DS.getTypeSpecTypeLoc());
}
};
class DeclaratorLocFiller : public TypeLocVisitor<DeclaratorLocFiller> {
ASTContext &Context;
const DeclaratorChunk &Chunk;
public:
DeclaratorLocFiller(ASTContext &Context, const DeclaratorChunk &Chunk)
: Context(Context), Chunk(Chunk) {}
void VisitQualifiedTypeLoc(QualifiedTypeLoc TL) {
llvm_unreachable("qualified type locs not expected here!");
}
void VisitAttributedTypeLoc(AttributedTypeLoc TL) {
fillAttributedTypeLoc(TL, Chunk.getAttrs());
}
void VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::BlockPointer);
TL.setCaretLoc(Chunk.Loc);
}
void VisitPointerTypeLoc(PointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Pointer);
TL.setStarLoc(Chunk.Loc);
}
void VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Pointer);
TL.setStarLoc(Chunk.Loc);
}
void VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::MemberPointer);
const CXXScopeSpec& SS = Chunk.Mem.Scope();
NestedNameSpecifierLoc NNSLoc = SS.getWithLocInContext(Context);
const Type* ClsTy = TL.getClass();
QualType ClsQT = QualType(ClsTy, 0);
TypeSourceInfo *ClsTInfo = Context.CreateTypeSourceInfo(ClsQT, 0);
TypeLoc ClsTL = ClsTInfo->getTypeLoc();
switch (NNSLoc.getNestedNameSpecifier()->getKind()) {
case NestedNameSpecifier::Identifier:
assert(isa<DependentNameType>(ClsTy) && "Unexpected TypeLoc");
{
DependentNameTypeLoc DNTLoc = cast<DependentNameTypeLoc>(ClsTL);
DNTLoc.setElaboratedKeywordLoc(SourceLocation());
DNTLoc.setQualifierLoc(NNSLoc.getPrefix());
DNTLoc.setNameLoc(NNSLoc.getLocalBeginLoc());
}
break;
case NestedNameSpecifier::TypeSpec:
case NestedNameSpecifier::TypeSpecWithTemplate:
if (isa<ElaboratedType>(ClsTy)) {
ElaboratedTypeLoc ETLoc = *cast<ElaboratedTypeLoc>(&ClsTL);
ETLoc.setElaboratedKeywordLoc(SourceLocation());
ETLoc.setQualifierLoc(NNSLoc.getPrefix());
TypeLoc NamedTL = ETLoc.getNamedTypeLoc();
NamedTL.initializeFullCopy(NNSLoc.getTypeLoc());
} else {
ClsTL.initializeFullCopy(NNSLoc.getTypeLoc());
}
break;
case NestedNameSpecifier::Namespace:
case NestedNameSpecifier::NamespaceAlias:
case NestedNameSpecifier::Global:
llvm_unreachable("Nested-name-specifier must name a type");
}
TL.setStarLoc(Chunk.Loc);
TL.setClassTInfo(ClsTInfo);
}
void VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Reference);
TL.setAmpLoc(Chunk.Loc);
}
void VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Reference);
assert(!Chunk.Ref.LValueRef);
TL.setAmpAmpLoc(Chunk.Loc);
}
void VisitArrayTypeLoc(ArrayTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Array);
TL.setLBracketLoc(Chunk.Loc);
TL.setRBracketLoc(Chunk.EndLoc);
TL.setSizeExpr(static_cast<Expr*>(Chunk.Arr.NumElts));
}
void VisitFunctionTypeLoc(FunctionTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Function);
TL.setLocalRangeBegin(Chunk.Loc);
TL.setLocalRangeEnd(Chunk.EndLoc);
const DeclaratorChunk::FunctionTypeInfo &FTI = Chunk.Fun;
for (unsigned i = 0, e = TL.getNumArgs(), tpi = 0; i != e; ++i) {
ParmVarDecl *Param = cast<ParmVarDecl>(FTI.ArgInfo[i].Param);
TL.setArg(tpi++, Param);
}
}
void VisitParenTypeLoc(ParenTypeLoc TL) {
assert(Chunk.Kind == DeclaratorChunk::Paren);
TL.setLParenLoc(Chunk.Loc);
TL.setRParenLoc(Chunk.EndLoc);
}
void VisitTypeLoc(TypeLoc TL) {
llvm_unreachable("unsupported TypeLoc kind in declarator!");
}
};
}
TypeSourceInfo *
Sema::GetTypeSourceInfoForDeclarator(Declarator &D, QualType T,
TypeSourceInfo *ReturnTypeInfo) {
TypeSourceInfo *TInfo = Context.CreateTypeSourceInfo(T);
UnqualTypeLoc CurrTL = TInfo->getTypeLoc().getUnqualifiedLoc();
if (isa<PackExpansionType>(T)) {
cast<PackExpansionTypeLoc>(CurrTL).setEllipsisLoc(D.getEllipsisLoc());
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
for (unsigned i = 0, e = D.getNumTypeObjects(); i != e; ++i) {
while (isa<AttributedTypeLoc>(CurrTL)) {
AttributedTypeLoc TL = cast<AttributedTypeLoc>(CurrTL);
fillAttributedTypeLoc(TL, D.getTypeObject(i).getAttrs());
CurrTL = TL.getNextTypeLoc().getUnqualifiedLoc();
}
DeclaratorLocFiller(Context, D.getTypeObject(i)).Visit(CurrTL);
CurrTL = CurrTL.getNextTypeLoc().getUnqualifiedLoc();
}
if (ReturnTypeInfo) {
TypeLoc TL = ReturnTypeInfo->getTypeLoc();
assert(TL.getFullDataSize() == CurrTL.getFullDataSize());
memcpy(CurrTL.getOpaqueData(), TL.getOpaqueData(), TL.getFullDataSize());
} else {
TypeSpecLocFiller(Context, D.getDeclSpec()).Visit(CurrTL);
}
return TInfo;
}
ParsedType Sema::CreateParsedType(QualType T, TypeSourceInfo *TInfo) {
LocInfoType *LocT = (LocInfoType*)BumpAlloc.Allocate(sizeof(LocInfoType),
TypeAlignment);
new (LocT) LocInfoType(T, TInfo);
assert(LocT->getTypeClass() != T->getTypeClass() &&
"LocInfoType's TypeClass conflicts with an existing Type class");
return ParsedType::make(QualType(LocT, 0));
}
void LocInfoType::getAsStringInternal(std::string &Str,
const PrintingPolicy &Policy) const {
llvm_unreachable("LocInfoType leaked into the type system; an opaque TypeTy*"
" was used directly instead of getting the QualType through"
" GetTypeFromParser");
}
TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
TypeSourceInfo *TInfo = GetTypeForDeclarator(D, S);
QualType T = TInfo->getType();
if (D.isInvalidType())
return true;
if (D.getContext() != Declarator::ObjCParameterContext)
checkUnusedDeclAttributes(D);
if (getLangOpts().CPlusPlus) {
CheckExtraCXXDefaultArguments(D);
}
return CreateParsedType(T, TInfo);
}
ParsedType Sema::ActOnObjCInstanceType(SourceLocation Loc) {
QualType T = Context.getObjCInstanceType();
TypeSourceInfo *TInfo = Context.getTrivialTypeSourceInfo(T, Loc);
return CreateParsedType(T, TInfo);
}
static void HandleAddressSpaceTypeAttribute(QualType &Type,
const AttributeList &Attr, Sema &S){
if (Type.getAddressSpace()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_multiple_qualifiers);
Attr.setInvalid();
return;
}
if (Type->isFunctionType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_function_type);
Attr.setInvalid();
return;
}
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Attr.setInvalid();
return;
}
Expr *ASArgExpr = static_cast<Expr *>(Attr.getArg(0));
llvm::APSInt addrSpace(32);
if (ASArgExpr->isTypeDependent() || ASArgExpr->isValueDependent() ||
!ASArgExpr->isIntegerConstantExpr(addrSpace, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_not_int)
<< ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
}
if (addrSpace.isSigned()) {
if (addrSpace.isNegative()) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_negative)
<< ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
}
addrSpace.setIsSigned(false);
}
llvm::APSInt max(addrSpace.getBitWidth());
max = Qualifiers::MaxAddressSpace;
if (addrSpace > max) {
S.Diag(Attr.getLoc(), diag::err_attribute_address_space_too_high)
<< Qualifiers::MaxAddressSpace << ASArgExpr->getSourceRange();
Attr.setInvalid();
return;
}
unsigned ASIdx = static_cast<unsigned>(addrSpace.getZExtValue());
Type = S.Context.getAddrSpaceQualType(Type, ASIdx);
}
static bool hasDirectOwnershipQualifier(QualType type) {
assert(type.getQualifiers().hasObjCLifetime());
while (true) {
if (const AttributedType *attr = dyn_cast<AttributedType>(type)) {
if (attr->getAttrKind() == AttributedType::attr_objc_ownership)
return true;
type = attr->getModifiedType();
} else if (const ParenType *paren = dyn_cast<ParenType>(type)) {
type = paren->getInnerType();
} else {
return false;
}
}
}
static bool handleObjCOwnershipTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType &type) {
bool NonObjCPointer = false;
if (!type->isDependentType()) {
if (const PointerType *ptr = type->getAs<PointerType>()) {
QualType pointee = ptr->getPointeeType();
if (pointee->isObjCRetainableType() || pointee->isPointerType())
return false;
NonObjCPointer = true;
} else if (!type->isObjCRetainableType()) {
return false;
}
}
Sema &S = state.getSema();
SourceLocation AttrLoc = attr.getLoc();
if (AttrLoc.isMacroID())
AttrLoc = S.getSourceManager().getImmediateExpansionRange(AttrLoc).first;
if (!attr.getParameterName()) {
S.Diag(AttrLoc, diag::err_attribute_argument_n_not_string)
<< "objc_ownership" << 1;
attr.setInvalid();
return true;
}
if (!S.getLangOpts().ObjCAutoRefCount)
return true;
Qualifiers::ObjCLifetime lifetime;
if (attr.getParameterName()->isStr("none"))
lifetime = Qualifiers::OCL_ExplicitNone;
else if (attr.getParameterName()->isStr("strong"))
lifetime = Qualifiers::OCL_Strong;
else if (attr.getParameterName()->isStr("weak"))
lifetime = Qualifiers::OCL_Weak;
else if (attr.getParameterName()->isStr("autoreleasing"))
lifetime = Qualifiers::OCL_Autoreleasing;
else {
S.Diag(AttrLoc, diag::warn_attribute_type_not_supported)
<< "objc_ownership" << attr.getParameterName();
attr.setInvalid();
return true;
}
SplitQualType underlyingType = type.split();
if (Qualifiers::ObjCLifetime previousLifetime
= type.getQualifiers().getObjCLifetime()) {
if (hasDirectOwnershipQualifier(type)) {
S.Diag(AttrLoc, diag::err_attr_objc_ownership_redundant)
<< type;
return true;
}
if (previousLifetime != lifetime) {
while (!underlyingType.Quals.hasObjCLifetime()) {
underlyingType = underlyingType.getSingleStepDesugaredType();
}
underlyingType.Quals.removeObjCLifetime();
}
}
underlyingType.Quals.addObjCLifetime(lifetime);
if (NonObjCPointer) {
StringRef name = attr.getName()->getName();
switch (lifetime) {
case Qualifiers::OCL_None:
case Qualifiers::OCL_ExplicitNone:
break;
case Qualifiers::OCL_Strong: name = "__strong"; break;
case Qualifiers::OCL_Weak: name = "__weak"; break;
case Qualifiers::OCL_Autoreleasing: name = "__autoreleasing"; break;
}
S.Diag(AttrLoc, diag::warn_objc_object_attribute_wrong_type)
<< name << type;
}
QualType origType = type;
if (!NonObjCPointer)
type = S.Context.getQualifiedType(underlyingType);
if (AttrLoc.isValid())
type = S.Context.getAttributedType(AttributedType::attr_objc_ownership,
origType, type);
if (lifetime == Qualifiers::OCL_Weak &&
!S.getLangOpts().ObjCARCWeak && !NonObjCPointer) {
if (S.DelayedDiagnostics.shouldDelayDiagnostics()) {
S.DelayedDiagnostics.add(
sema::DelayedDiagnostic::makeForbiddenType(
S.getSourceManager().getExpansionLoc(AttrLoc),
diag::err_arc_weak_no_runtime, type, 0));
} else {
S.Diag(AttrLoc, diag::err_arc_weak_no_runtime);
}
attr.setInvalid();
return true;
}
if (lifetime == Qualifiers::OCL_Weak) {
QualType T = type;
while (const PointerType *ptr = T->getAs<PointerType>())
T = ptr->getPointeeType();
if (const ObjCObjectPointerType *ObjT = T->getAs<ObjCObjectPointerType>()) {
if (ObjCInterfaceDecl *Class = ObjT->getInterfaceDecl()) {
if (Class->isArcWeakrefUnavailable()) {
S.Diag(AttrLoc, diag::err_arc_unsupported_weak_class);
S.Diag(ObjT->getInterfaceDecl()->getLocation(),
diag::note_class_declared);
}
}
}
}
return true;
}
static bool handleObjCGCTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType &type) {
Sema &S = state.getSema();
if (!type->isPointerType() &&
!type->isObjCObjectPointerType() &&
!type->isBlockPointerType())
return false;
if (type.getObjCGCAttr() != Qualifiers::GCNone) {
S.Diag(attr.getLoc(), diag::err_attribute_multiple_objc_gc);
attr.setInvalid();
return true;
}
if (!attr.getParameterName()) {
S.Diag(attr.getLoc(), diag::err_attribute_argument_n_not_string)
<< "objc_gc" << 1;
attr.setInvalid();
return true;
}
Qualifiers::GC GCAttr;
if (attr.getNumArgs() != 0) {
S.Diag(attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
attr.setInvalid();
return true;
}
if (attr.getParameterName()->isStr("weak"))
GCAttr = Qualifiers::Weak;
else if (attr.getParameterName()->isStr("strong"))
GCAttr = Qualifiers::Strong;
else {
S.Diag(attr.getLoc(), diag::warn_attribute_type_not_supported)
<< "objc_gc" << attr.getParameterName();
attr.setInvalid();
return true;
}
QualType origType = type;
type = S.Context.getObjCGCQualType(origType, GCAttr);
if (attr.getLoc().isValid())
type = S.Context.getAttributedType(AttributedType::attr_objc_gc,
origType, type);
return true;
}
namespace {
struct FunctionTypeUnwrapper {
enum WrapKind {
Desugar,
Parens,
Pointer,
BlockPointer,
Reference,
MemberPointer
};
QualType Original;
const FunctionType *Fn;
SmallVector<unsigned char , 8> Stack;
FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
while (true) {
const Type *Ty = T.getTypePtr();
if (isa<FunctionType>(Ty)) {
Fn = cast<FunctionType>(Ty);
return;
} else if (isa<ParenType>(Ty)) {
T = cast<ParenType>(Ty)->getInnerType();
Stack.push_back(Parens);
} else if (isa<PointerType>(Ty)) {
T = cast<PointerType>(Ty)->getPointeeType();
Stack.push_back(Pointer);
} else if (isa<BlockPointerType>(Ty)) {
T = cast<BlockPointerType>(Ty)->getPointeeType();
Stack.push_back(BlockPointer);
} else if (isa<MemberPointerType>(Ty)) {
T = cast<MemberPointerType>(Ty)->getPointeeType();
Stack.push_back(MemberPointer);
} else if (isa<ReferenceType>(Ty)) {
T = cast<ReferenceType>(Ty)->getPointeeType();
Stack.push_back(Reference);
} else {
const Type *DTy = Ty->getUnqualifiedDesugaredType();
if (Ty == DTy) {
Fn = 0;
return;
}
T = QualType(DTy, 0);
Stack.push_back(Desugar);
}
}
}
bool isFunctionType() const { return (Fn != 0); }
const FunctionType *get() const { return Fn; }
QualType wrap(Sema &S, const FunctionType *New) {
if (New == get()) return Original;
Fn = New;
return wrap(S.Context, Original, 0);
}
private:
QualType wrap(ASTContext &C, QualType Old, unsigned I) {
if (I == Stack.size())
return C.getQualifiedType(Fn, Old.getQualifiers());
SplitQualType SplitOld = Old.split();
if (SplitOld.Quals.empty())
return wrap(C, SplitOld.Ty, I);
return C.getQualifiedType(wrap(C, SplitOld.Ty, I), SplitOld.Quals);
}
QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
if (I == Stack.size()) return QualType(Fn, 0);
switch (static_cast<WrapKind>(Stack[I++])) {
case Desugar:
return wrap(C, Old->getUnqualifiedDesugaredType(), I);
case Parens: {
QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
return C.getParenType(New);
}
case Pointer: {
QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
return C.getPointerType(New);
}
case BlockPointer: {
QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
return C.getBlockPointerType(New);
}
case MemberPointer: {
const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
QualType New = wrap(C, OldMPT->getPointeeType(), I);
return C.getMemberPointerType(New, OldMPT->getClass());
}
case Reference: {
const ReferenceType *OldRef = cast<ReferenceType>(Old);
QualType New = wrap(C, OldRef->getPointeeType(), I);
if (isa<LValueReferenceType>(OldRef))
return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
else
return C.getRValueReferenceType(New);
}
}
llvm_unreachable("unknown wrapping kind");
}
};
}
static bool handleFunctionTypeAttr(TypeProcessingState &state,
AttributeList &attr,
QualType &type) {
Sema &S = state.getSema();
FunctionTypeUnwrapper unwrapped(S, type);
if (attr.getKind() == AttributeList::AT_NoReturn) {
if (S.CheckNoReturnAttr(attr))
return true;
if (!unwrapped.isFunctionType())
return false;
FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withNoReturn(true);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
if (attr.getKind() == AttributeList::AT_NSReturnsRetained) {
assert(S.getLangOpts().ObjCAutoRefCount &&
"ns_returns_retained treated as type attribute in non-ARC");
if (attr.getNumArgs()) return true;
if (!unwrapped.isFunctionType())
return false;
FunctionType::ExtInfo EI
= unwrapped.get()->getExtInfo().withProducesResult(true);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
if (attr.getKind() == AttributeList::AT_Regparm) {
unsigned value;
if (S.CheckRegparmAttr(attr, value))
return true;
if (!unwrapped.isFunctionType())
return false;
const FunctionType *fn = unwrapped.get();
CallingConv CC = fn->getCallConv();
if (CC == CC_X86FastCall) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< FunctionType::getNameForCallConv(CC)
<< "regparm";
attr.setInvalid();
return true;
}
FunctionType::ExtInfo EI =
unwrapped.get()->getExtInfo().withRegParm(value);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
if (!unwrapped.isFunctionType()) return false;
CallingConv CC;
if (S.CheckCallingConvAttr(attr, CC))
return true;
const FunctionType *fn = unwrapped.get();
CallingConv CCOld = fn->getCallConv();
if (S.Context.getCanonicalCallConv(CC) ==
S.Context.getCanonicalCallConv(CCOld)) {
FunctionType::ExtInfo EI= unwrapped.get()->getExtInfo().withCallingConv(CC);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
if (CCOld != (S.LangOpts.MRTD ? CC_X86StdCall : CC_Default)) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< FunctionType::getNameForCallConv(CC)
<< FunctionType::getNameForCallConv(CCOld);
attr.setInvalid();
return true;
}
if (CC == CC_X86FastCall) {
if (isa<FunctionNoProtoType>(fn)) {
S.Diag(attr.getLoc(), diag::err_cconv_knr)
<< FunctionType::getNameForCallConv(CC);
attr.setInvalid();
return true;
}
const FunctionProtoType *FnP = cast<FunctionProtoType>(fn);
if (FnP->isVariadic()) {
S.Diag(attr.getLoc(), diag::err_cconv_varargs)
<< FunctionType::getNameForCallConv(CC);
attr.setInvalid();
return true;
}
if (fn->getHasRegParm()) {
S.Diag(attr.getLoc(), diag::err_attributes_are_not_compatible)
<< "regparm"
<< FunctionType::getNameForCallConv(CC);
attr.setInvalid();
return true;
}
}
FunctionType::ExtInfo EI = unwrapped.get()->getExtInfo().withCallingConv(CC);
type = unwrapped.wrap(S, S.Context.adjustFunctionType(unwrapped.get(), EI));
return true;
}
static void HandleOpenCLImageAccessAttribute(QualType& CurType,
const AttributeList &Attr,
Sema &S) {
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Attr.setInvalid();
return;
}
Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
llvm::APSInt arg(32);
if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
!sizeExpr->isIntegerConstantExpr(arg, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
<< "opencl_image_access" << sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
unsigned iarg = static_cast<unsigned>(arg.getZExtValue());
switch (iarg) {
case CLIA_read_only:
case CLIA_write_only:
case CLIA_read_write:
break;
default:
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
<< sizeExpr->getSourceRange();
Attr.setInvalid();
break;
}
}
static void HandleVectorSizeAttr(QualType& CurType, const AttributeList &Attr,
Sema &S) {
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Attr.setInvalid();
return;
}
Expr *sizeExpr = static_cast<Expr *>(Attr.getArg(0));
llvm::APSInt vecSize(32);
if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
<< "vector_size" << sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
if (!CurType->isIntegerType() && !CurType->isRealFloatingType()) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
Attr.setInvalid();
return;
}
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
if (vectorSize % typeSize) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
<< sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
if (vectorSize == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
<< sizeExpr->getSourceRange();
Attr.setInvalid();
return;
}
CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
VectorType::GenericVector);
}
static void HandleExtVectorTypeAttr(QualType &CurType,
const AttributeList &Attr,
Sema &S) {
Expr *sizeExpr;
if (Attr.getParameterName()) {
CXXScopeSpec SS;
SourceLocation TemplateKWLoc;
UnqualifiedId id;
id.setIdentifier(Attr.getParameterName(), Attr.getLoc());
ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
id, false, false);
if (Size.isInvalid())
return;
sizeExpr = Size.get();
} else {
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
return;
}
sizeExpr = Attr.getArg(0);
}
QualType T = S.BuildExtVectorType(CurType, sizeExpr, Attr.getLoc());
if (!T.isNull())
CurType = T;
}
static void HandleNeonVectorTypeAttr(QualType& CurType,
const AttributeList &Attr, Sema &S,
VectorType::VectorKind VecKind,
const char *AttrName) {
if (Attr.getNumArgs() != 1) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1;
Attr.setInvalid();
return;
}
Expr *numEltsExpr = static_cast<Expr *>(Attr.getArg(0));
llvm::APSInt numEltsInt(32);
if (numEltsExpr->isTypeDependent() || numEltsExpr->isValueDependent() ||
!numEltsExpr->isIntegerConstantExpr(numEltsInt, S.Context)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_not_int)
<< AttrName << numEltsExpr->getSourceRange();
Attr.setInvalid();
return;
}
const BuiltinType* BTy = CurType->getAs<BuiltinType>();
if (!BTy ||
(VecKind == VectorType::NeonPolyVector &&
BTy->getKind() != BuiltinType::SChar &&
BTy->getKind() != BuiltinType::Short) ||
(BTy->getKind() != BuiltinType::SChar &&
BTy->getKind() != BuiltinType::UChar &&
BTy->getKind() != BuiltinType::Short &&
BTy->getKind() != BuiltinType::UShort &&
BTy->getKind() != BuiltinType::Int &&
BTy->getKind() != BuiltinType::UInt &&
BTy->getKind() != BuiltinType::LongLong &&
BTy->getKind() != BuiltinType::ULongLong &&
BTy->getKind() != BuiltinType::Float)) {
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) <<CurType;
Attr.setInvalid();
return;
}
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
unsigned numElts = static_cast<unsigned>(numEltsInt.getZExtValue());
unsigned vecSize = typeSize * numElts;
if (vecSize != 64 && vecSize != 128) {
S.Diag(Attr.getLoc(), diag::err_attribute_bad_neon_vector_size) << CurType;
Attr.setInvalid();
return;
}
CurType = S.Context.getVectorType(CurType, numElts, VecKind);
}
static void processTypeAttrs(TypeProcessingState &state, QualType &type,
bool isDeclSpec, AttributeList *attrs) {
AttributeList *next;
do {
AttributeList &attr = *attrs;
next = attr.getNext();
if (attr.isInvalid())
continue;
switch (attr.getKind()) {
default: break;
case AttributeList::AT_MayAlias:
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_AddressSpace:
HandleAddressSpaceTypeAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
OBJC_POINTER_TYPE_ATTRS_CASELIST:
if (!handleObjCPointerTypeAttr(state, attr, type))
distributeObjCPointerTypeAttr(state, attr, type);
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_VectorSize:
HandleVectorSizeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_ExtVectorType:
if (state.getDeclarator().getDeclSpec().getStorageClassSpec()
!= DeclSpec::SCS_typedef)
HandleExtVectorTypeAttr(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_NeonVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonVector, "neon_vector_type");
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_NeonPolyVectorType:
HandleNeonVectorTypeAttr(type, attr, state.getSema(),
VectorType::NeonPolyVector,
"neon_polyvector_type");
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_OpenCLImageAccess:
HandleOpenCLImageAccessAttribute(type, attr, state.getSema());
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_Win64:
case AttributeList::AT_Ptr32:
case AttributeList::AT_Ptr64:
attr.setUsedAsTypeAttr();
break;
case AttributeList::AT_NSReturnsRetained:
if (!state.getSema().getLangOpts().ObjCAutoRefCount)
break;
FUNCTION_TYPE_ATTRS_CASELIST:
attr.setUsedAsTypeAttr();
if (isDeclSpec)
distributeFunctionTypeAttrFromDeclSpec(state, attr, type);
else if (!handleFunctionTypeAttr(state, attr, type))
distributeFunctionTypeAttr(state, attr, type);
break;
}
} while ((attrs = next));
}
bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){
QualType T = E->getType();
if (!T->isIncompleteType())
return false;
if (T->isIncompleteArrayType()) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
if (Var->isStaticDataMember() &&
Var->getInstantiatedFromStaticDataMember()) {
MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
assert(MSInfo && "Missing member specialization information?");
if (MSInfo->getTemplateSpecializationKind()
!= TSK_ExplicitSpecialization) {
if (MSInfo->getPointOfInstantiation().isInvalid()) {
MSInfo->setPointOfInstantiation(E->getLocStart());
if (ASTMutationListener *L = getASTMutationListener())
L->StaticDataMemberInstantiated(Var);
}
InstantiateStaticDataMemberDefinition(E->getExprLoc(), Var);
if (VarDecl *Def = Var->getDefinition()) {
DRE->setDecl(Def);
T = Def->getType();
DRE->setType(T);
E->setType(T);
}
}
}
}
}
}
if (const ReferenceType *Ref = T->getAs<ReferenceType>())
T = Ref->getPointeeType();
return RequireCompleteType(E->getExprLoc(), T, Diagnoser);
}
namespace {
struct TypeDiagnoserDiag : Sema::TypeDiagnoser {
unsigned DiagID;
TypeDiagnoserDiag(unsigned DiagID)
: Sema::TypeDiagnoser(DiagID == 0), DiagID(DiagID) {}
virtual void diagnose(Sema &S, SourceLocation Loc, QualType T) {
if (Suppressed) return;
S.Diag(Loc, DiagID) << T;
}
};
}
bool Sema::RequireCompleteExprType(Expr *E, unsigned DiagID) {
TypeDiagnoserDiag Diagnoser(DiagID);
return RequireCompleteExprType(E, Diagnoser);
}
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
NamedDecl *Def = 0;
if (!T->isIncompleteType(&Def)) {
if (!Diagnoser.Suppressed && Def && !LookupResult::isVisible(Def)) {
if (isSFINAEContext() || HiddenDefinitions.insert(Def)) {
Diag(Loc, diag::err_module_private_definition) << T;
Diag(Def->getLocation(), diag::note_previous_definition);
}
}
return false;
}
const TagType *Tag = T->getAs<TagType>();
const ObjCInterfaceType *IFace = 0;
if (Tag) {
if (Tag->getDecl()->isInvalidDecl())
return true;
if (Tag->getDecl()->hasExternalLexicalStorage()) {
Context.getExternalSource()->CompleteType(Tag->getDecl());
if (!Tag->isIncompleteType())
return false;
}
}
else if ((IFace = T->getAs<ObjCInterfaceType>())) {
if (IFace->getDecl()->isInvalidDecl())
return true;
if (IFace->getDecl()->hasExternalLexicalStorage()) {
Context.getExternalSource()->CompleteType(IFace->getDecl());
if (!IFace->isIncompleteType())
return false;
}
}
QualType MaybeTemplate = T;
while (const ConstantArrayType *Array
= Context.getAsConstantArrayType(MaybeTemplate))
MaybeTemplate = Array->getElementType();
if (const RecordType *Record = MaybeTemplate->getAs<RecordType>()) {
if (ClassTemplateSpecializationDecl *ClassTemplateSpec
= dyn_cast<ClassTemplateSpecializationDecl>(Record->getDecl())) {
if (ClassTemplateSpec->getSpecializationKind() == TSK_Undeclared)
return InstantiateClassTemplateSpecialization(Loc, ClassTemplateSpec,
TSK_ImplicitInstantiation,
!Diagnoser.Suppressed);
} else if (CXXRecordDecl *Rec
= dyn_cast<CXXRecordDecl>(Record->getDecl())) {
CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass();
if (!Rec->isBeingDefined() && Pattern) {
MemberSpecializationInfo *MSI = Rec->getMemberSpecializationInfo();
assert(MSI && "Missing member specialization information?");
if (MSI->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
return InstantiateClass(Loc, Rec, Pattern,
getTemplateInstantiationArgs(Rec),
TSK_ImplicitInstantiation,
!Diagnoser.Suppressed);
}
}
}
if (Diagnoser.Suppressed)
return true;
Diagnoser.diagnose(*this, Loc, T);
if (Tag && !Tag->getDecl()->isInvalidDecl())
Diag(Tag->getDecl()->getLocation(),
Tag->isBeingDefined() ? diag::note_type_being_defined
: diag::note_forward_declaration)
<< QualType(Tag, 0);
if (IFace && !IFace->getDecl()->isInvalidDecl())
Diag(IFace->getDecl()->getLocation(), diag::note_forward_class);
return true;
}
bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
unsigned DiagID) {
TypeDiagnoserDiag Diagnoser(DiagID);
return RequireCompleteType(Loc, T, Diagnoser);
}
static unsigned getLiteralDiagFromTagKind(TagTypeKind Tag) {
switch (Tag) {
case TTK_Struct: return 0;
case TTK_Interface: return 1;
case TTK_Class: return 2;
default: llvm_unreachable("Invalid tag kind for literal type diagnostic!");
}
}
bool Sema::RequireLiteralType(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
assert(!T->isDependentType() && "type should not be dependent");
QualType ElemType = Context.getBaseElementType(T);
RequireCompleteType(Loc, ElemType, 0);
if (T->isLiteralType())
return false;
if (Diagnoser.Suppressed)
return true;
Diagnoser.diagnose(*this, Loc, T);
if (T->isVariableArrayType())
return true;
const RecordType *RT = ElemType->getAs<RecordType>();
if (!RT)
return true;
const CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
if (!RD->isCompleteDefinition()) {
RequireCompleteType(Loc, ElemType, diag::note_non_literal_incomplete, T);
return true;
}
if (RD->getNumVBases()) {
Diag(RD->getLocation(), diag::note_non_literal_virtual_base)
<< getLiteralDiagFromTagKind(RD->getTagKind()) << RD->getNumVBases();
for (CXXRecordDecl::base_class_const_iterator I = RD->vbases_begin(),
E = RD->vbases_end(); I != E; ++I)
Diag(I->getLocStart(),
diag::note_constexpr_virtual_base_here) << I->getSourceRange();
} else if (!RD->isAggregate() && !RD->hasConstexprNonCopyMoveConstructor() &&
!RD->hasTrivialDefaultConstructor()) {
Diag(RD->getLocation(), diag::note_non_literal_no_constexpr_ctors) << RD;
} else if (RD->hasNonLiteralTypeFieldsOrBases()) {
for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(),
E = RD->bases_end(); I != E; ++I) {
if (!I->getType()->isLiteralType()) {
Diag(I->getLocStart(),
diag::note_non_literal_base_class)
<< RD << I->getType() << I->getSourceRange();
return true;
}
}
for (CXXRecordDecl::field_iterator I = RD->field_begin(),
E = RD->field_end(); I != E; ++I) {
if (!I->getType()->isLiteralType() ||
I->getType().isVolatileQualified()) {
Diag(I->getLocation(), diag::note_non_literal_field)
<< RD << *I << I->getType()
<< I->getType().isVolatileQualified();
return true;
}
}
} else if (!RD->hasTrivialDestructor()) {
CXXDestructorDecl *Dtor = RD->getDestructor();
assert(Dtor && "class has literal fields and bases but no dtor?");
if (!Dtor)
return true;
Diag(Dtor->getLocation(), Dtor->isUserProvided() ?
diag::note_non_literal_user_provided_dtor :
diag::note_non_literal_nontrivial_dtor) << RD;
}
return true;
}
bool Sema::RequireLiteralType(SourceLocation Loc, QualType T, unsigned DiagID) {
TypeDiagnoserDiag Diagnoser(DiagID);
return RequireLiteralType(Loc, T, Diagnoser);
}
QualType Sema::getElaboratedType(ElaboratedTypeKeyword Keyword,
const CXXScopeSpec &SS, QualType T) {
if (T.isNull())
return T;
NestedNameSpecifier *NNS;
if (SS.isValid())
NNS = static_cast<NestedNameSpecifier *>(SS.getScopeRep());
else {
if (Keyword == ETK_None)
return T;
NNS = 0;
}
return Context.getElaboratedType(Keyword, NNS, T);
}
QualType Sema::BuildTypeofExprType(Expr *E, SourceLocation Loc) {
ExprResult ER = CheckPlaceholderExpr(E);
if (ER.isInvalid()) return QualType();
E = ER.take();
if (!E->isTypeDependent()) {
QualType T = E->getType();
if (const TagType *TT = T->getAs<TagType>())
DiagnoseUseOfDecl(TT->getDecl(), E->getExprLoc());
}
return Context.getTypeOfExprType(E);
}
static QualType getDecltypeForExpr(Sema &S, Expr *E) {
if (E->isTypeDependent())
return S.Context.DependentTy;
if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
if (const ValueDecl *VD = dyn_cast<ValueDecl>(DRE->getDecl()))
return VD->getType();
} else if (const MemberExpr *ME = dyn_cast<MemberExpr>(E)) {
if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
return FD->getType();
} else if (const ObjCIvarRefExpr *IR = dyn_cast<ObjCIvarRefExpr>(E)) {
return IR->getDecl()->getType();
} else if (const ObjCPropertyRefExpr *PR = dyn_cast<ObjCPropertyRefExpr>(E)) {
if (PR->isExplicitProperty())
return PR->getExplicitProperty()->getType();
}
using namespace sema;
if (S.getCurLambda()) {
if (isa<ParenExpr>(E)) {
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->IgnoreParens())) {
if (VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
QualType T = S.getCapturedDeclRefType(Var, DRE->getLocation());
if (!T.isNull())
return S.Context.getLValueReferenceType(T);
}
}
}
}
QualType T = E->getType();
switch (E->getValueKind()) {
case VK_XValue: T = S.Context.getRValueReferenceType(T); break;
case VK_LValue: T = S.Context.getLValueReferenceType(T); break;
case VK_RValue: break;
}
return T;
}
QualType Sema::BuildDecltypeType(Expr *E, SourceLocation Loc) {
ExprResult ER = CheckPlaceholderExpr(E);
if (ER.isInvalid()) return QualType();
E = ER.take();
return Context.getDecltypeType(E, getDecltypeForExpr(*this, E));
}
QualType Sema::BuildUnaryTransformType(QualType BaseType,
UnaryTransformType::UTTKind UKind,
SourceLocation Loc) {
switch (UKind) {
case UnaryTransformType::EnumUnderlyingType:
if (!BaseType->isDependentType() && !BaseType->isEnumeralType()) {
Diag(Loc, diag::err_only_enums_have_underlying_types);
return QualType();
} else {
QualType Underlying = BaseType;
if (!BaseType->isDependentType()) {
EnumDecl *ED = BaseType->getAs<EnumType>()->getDecl();
assert(ED && "EnumType has no EnumDecl");
DiagnoseUseOfDecl(ED, Loc);
Underlying = ED->getIntegerType();
}
assert(!Underlying.isNull());
return Context.getUnaryTransformType(BaseType, Underlying,
UnaryTransformType::EnumUnderlyingType);
}
}
llvm_unreachable("unknown unary transform type");
}
QualType Sema::BuildAtomicType(QualType T, SourceLocation Loc) {
if (!T->isDependentType()) {
if (RequireCompleteType(Loc, T, diag::err_atomic_specifier_bad_type, 0))
return QualType();
int DisallowedKind = -1;
if (T->isArrayType())
DisallowedKind = 1;
else if (T->isFunctionType())
DisallowedKind = 2;
else if (T->isReferenceType())
DisallowedKind = 3;
else if (T->isAtomicType())
DisallowedKind = 4;
else if (T.hasQualifiers())
DisallowedKind = 5;
else if (!T.isTriviallyCopyableType(Context))
DisallowedKind = 6;
if (DisallowedKind != -1) {
Diag(Loc, diag::err_atomic_specifier_bad_type) << DisallowedKind << T;
return QualType();
}
}
return Context.getAtomicType(T);
}