зеркало из https://github.com/microsoft/clang-1.git
Update Parser::ParseTypeName to return a TypeResult, which also tells
us whether there was an error in trying to parse a type-name (type-id in C++). This allows propagation of errors further in the compiler, suppressing more bogus error messages. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@64922 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
e53f8206eb
Коммит
809070a886
|
@ -105,6 +105,7 @@ public:
|
||||||
typedef Action::StmtResult StmtResult;
|
typedef Action::StmtResult StmtResult;
|
||||||
typedef Action::BaseResult BaseResult;
|
typedef Action::BaseResult BaseResult;
|
||||||
typedef Action::MemInitResult MemInitResult;
|
typedef Action::MemInitResult MemInitResult;
|
||||||
|
typedef Action::TypeResult TypeResult;
|
||||||
|
|
||||||
typedef Action::OwningExprResult OwningExprResult;
|
typedef Action::OwningExprResult OwningExprResult;
|
||||||
typedef Action::OwningStmtResult OwningStmtResult;
|
typedef Action::OwningStmtResult OwningStmtResult;
|
||||||
|
@ -912,8 +913,7 @@ private:
|
||||||
TPResult TryParseFunctionDeclarator();
|
TPResult TryParseFunctionDeclarator();
|
||||||
TPResult TryParseBracketDeclarator();
|
TPResult TryParseBracketDeclarator();
|
||||||
|
|
||||||
|
TypeResult ParseTypeName();
|
||||||
TypeTy *ParseTypeName();
|
|
||||||
void ParseBlockId();
|
void ParseBlockId();
|
||||||
// EndLoc, if non-NULL, is filled with the location of the last token of
|
// EndLoc, if non-NULL, is filled with the location of the last token of
|
||||||
// the attribute list.
|
// the attribute list.
|
||||||
|
|
|
@ -28,7 +28,7 @@ using namespace clang;
|
||||||
/// specifier-qualifier-list abstract-declarator[opt]
|
/// specifier-qualifier-list abstract-declarator[opt]
|
||||||
///
|
///
|
||||||
/// Called type-id in C++.
|
/// Called type-id in C++.
|
||||||
Parser::TypeTy *Parser::ParseTypeName() {
|
Action::TypeResult Parser::ParseTypeName() {
|
||||||
// Parse the common declaration-specifiers piece.
|
// Parse the common declaration-specifiers piece.
|
||||||
DeclSpec DS;
|
DeclSpec DS;
|
||||||
ParseSpecifierQualifierList(DS);
|
ParseSpecifierQualifierList(DS);
|
||||||
|
@ -37,7 +37,10 @@ Parser::TypeTy *Parser::ParseTypeName() {
|
||||||
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
Declarator DeclaratorInfo(DS, Declarator::TypeNameContext);
|
||||||
ParseDeclarator(DeclaratorInfo);
|
ParseDeclarator(DeclaratorInfo);
|
||||||
|
|
||||||
return Actions.ActOnTypeName(CurScope, DeclaratorInfo).get();
|
if (DeclaratorInfo.getInvalidType())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return Actions.ActOnTypeName(CurScope, DeclaratorInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseAttributes - Parse a non-empty attributes list.
|
/// ParseAttributes - Parse a non-empty attributes list.
|
||||||
|
@ -2383,8 +2386,10 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OwningExprResult Result(ParseCastExpression(true/*isUnaryExpression*/));
|
OwningExprResult Result(ParseCastExpression(true/*isUnaryExpression*/));
|
||||||
if (Result.isInvalid())
|
if (Result.isInvalid()) {
|
||||||
|
DS.SetTypeSpecError();
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const char *PrevSpec = 0;
|
const char *PrevSpec = 0;
|
||||||
// Check for duplicate type specifiers.
|
// Check for duplicate type specifiers.
|
||||||
|
@ -2400,24 +2405,32 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
|
||||||
SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
|
SourceLocation LParenLoc = ConsumeParen(), RParenLoc;
|
||||||
|
|
||||||
if (isTypeIdInParens()) {
|
if (isTypeIdInParens()) {
|
||||||
TypeTy *Ty = ParseTypeName();
|
Action::TypeResult Ty = ParseTypeName();
|
||||||
|
|
||||||
assert(Ty && "Parser::ParseTypeofSpecifier(): missing type");
|
assert((Ty.isInvalid() || Ty.get()) &&
|
||||||
|
"Parser::ParseTypeofSpecifier(): missing type");
|
||||||
|
|
||||||
if (Tok.isNot(tok::r_paren)) {
|
if (Tok.isNot(tok::r_paren)) {
|
||||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RParenLoc = ConsumeParen();
|
RParenLoc = ConsumeParen();
|
||||||
|
|
||||||
|
if (Ty.isInvalid())
|
||||||
|
DS.SetTypeSpecError();
|
||||||
|
else {
|
||||||
const char *PrevSpec = 0;
|
const char *PrevSpec = 0;
|
||||||
// Check for duplicate type specifiers (e.g. "int typeof(int)").
|
// Check for duplicate type specifiers (e.g. "int typeof(int)").
|
||||||
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec, Ty))
|
if (DS.SetTypeSpecType(DeclSpec::TST_typeofType, StartLoc, PrevSpec,
|
||||||
|
Ty.get()))
|
||||||
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
Diag(StartLoc, diag::err_invalid_decl_spec_combination) << PrevSpec;
|
||||||
|
}
|
||||||
} else { // we have an expression.
|
} else { // we have an expression.
|
||||||
OwningExprResult Result(ParseExpression());
|
OwningExprResult Result(ParseExpression());
|
||||||
|
|
||||||
if (Result.isInvalid() || Tok.isNot(tok::r_paren)) {
|
if (Result.isInvalid() || Tok.isNot(tok::r_paren)) {
|
||||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
DS.SetTypeSpecError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
RParenLoc = ConsumeParen();
|
RParenLoc = ConsumeParen();
|
||||||
|
|
|
@ -939,18 +939,22 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
|
||||||
TypeTy *Ty = ParseTypeName();
|
TypeResult Ty = ParseTypeName();
|
||||||
|
|
||||||
if (Tok.isNot(tok::r_paren)) {
|
if (Tok.isNot(tok::r_paren)) {
|
||||||
Diag(Tok, diag::err_expected_rparen);
|
Diag(Tok, diag::err_expected_rparen);
|
||||||
return ExprError();
|
return ExprError();
|
||||||
}
|
}
|
||||||
Res = Actions.ActOnVAArg(StartLoc, Expr.release(), Ty, ConsumeParen());
|
if (Ty.isInvalid())
|
||||||
|
Res = ExprError();
|
||||||
|
else
|
||||||
|
Res = Actions.ActOnVAArg(StartLoc, Expr.release(), Ty.get(),
|
||||||
|
ConsumeParen());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tok::kw___builtin_offsetof: {
|
case tok::kw___builtin_offsetof: {
|
||||||
SourceLocation TypeLoc = Tok.getLocation();
|
SourceLocation TypeLoc = Tok.getLocation();
|
||||||
TypeTy *Ty = ParseTypeName();
|
TypeResult Ty = ParseTypeName();
|
||||||
|
|
||||||
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
@ -1001,9 +1005,12 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
Comps.back().LocEnd =
|
Comps.back().LocEnd =
|
||||||
MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
|
MatchRHSPunctuation(tok::r_square, Comps.back().LocStart);
|
||||||
} else if (Tok.is(tok::r_paren)) {
|
} else if (Tok.is(tok::r_paren)) {
|
||||||
Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc, Ty,
|
if (Ty.isInvalid())
|
||||||
&Comps[0], Comps.size(),
|
Res = ExprError();
|
||||||
ConsumeParen());
|
else
|
||||||
|
Res = Actions.ActOnBuiltinOffsetOf(CurScope, StartLoc, TypeLoc,
|
||||||
|
Ty.get(), &Comps[0],
|
||||||
|
Comps.size(), ConsumeParen());
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
// Error occurred.
|
// Error occurred.
|
||||||
|
@ -1075,18 +1082,23 @@ Parser::OwningExprResult Parser::ParseBuiltinPrimaryExpression() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case tok::kw___builtin_types_compatible_p:
|
case tok::kw___builtin_types_compatible_p:
|
||||||
TypeTy *Ty1 = ParseTypeName();
|
TypeResult Ty1 = ParseTypeName();
|
||||||
|
|
||||||
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
if (ExpectAndConsume(tok::comma, diag::err_expected_comma, "",tok::r_paren))
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
|
||||||
TypeTy *Ty2 = ParseTypeName();
|
TypeResult Ty2 = ParseTypeName();
|
||||||
|
|
||||||
if (Tok.isNot(tok::r_paren)) {
|
if (Tok.isNot(tok::r_paren)) {
|
||||||
Diag(Tok, diag::err_expected_rparen);
|
Diag(Tok, diag::err_expected_rparen);
|
||||||
return ExprError();
|
return ExprError();
|
||||||
}
|
}
|
||||||
Res = Actions.ActOnTypesCompatibleExpr(StartLoc, Ty1, Ty2, ConsumeParen());
|
|
||||||
|
if (Ty1.isInvalid() || Ty2.isInvalid())
|
||||||
|
Res = ExprError();
|
||||||
|
else
|
||||||
|
Res = Actions.ActOnTypesCompatibleExpr(StartLoc, Ty1.get(), Ty2.get(),
|
||||||
|
ConsumeParen());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1129,7 +1141,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType,
|
||||||
|
|
||||||
} else if (ExprType >= CompoundLiteral && isTypeIdInParens()) {
|
} else if (ExprType >= CompoundLiteral && isTypeIdInParens()) {
|
||||||
// Otherwise, this is a compound literal expression or cast expression.
|
// Otherwise, this is a compound literal expression or cast expression.
|
||||||
TypeTy *Ty = ParseTypeName();
|
TypeResult Ty = ParseTypeName();
|
||||||
|
|
||||||
// Match the ')'.
|
// Match the ')'.
|
||||||
if (Tok.is(tok::r_paren))
|
if (Tok.is(tok::r_paren))
|
||||||
|
@ -1142,17 +1154,21 @@ Parser::ParseParenExpression(ParenParseOption &ExprType,
|
||||||
Diag(OpenLoc, diag::ext_c99_compound_literal);
|
Diag(OpenLoc, diag::ext_c99_compound_literal);
|
||||||
Result = ParseInitializer();
|
Result = ParseInitializer();
|
||||||
ExprType = CompoundLiteral;
|
ExprType = CompoundLiteral;
|
||||||
if (!Result.isInvalid())
|
if (!Result.isInvalid() && !Ty.isInvalid())
|
||||||
return Actions.ActOnCompoundLiteral(OpenLoc, Ty, RParenLoc,
|
return Actions.ActOnCompoundLiteral(OpenLoc, Ty.get(), RParenLoc,
|
||||||
move(Result));
|
move(Result));
|
||||||
return move(Result);
|
return move(Result);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ExprType == CastExpr) {
|
if (ExprType == CastExpr) {
|
||||||
// Note that this doesn't parse the subsequence cast-expression, it just
|
// Note that this doesn't parse the subsequent cast-expression, it just
|
||||||
// returns the parsed type to the callee.
|
// returns the parsed type to the callee.
|
||||||
ExprType = CastExpr;
|
ExprType = CastExpr;
|
||||||
CastTy = Ty;
|
|
||||||
|
if (Ty.isInvalid())
|
||||||
|
return ExprError();
|
||||||
|
|
||||||
|
CastTy = Ty.get();
|
||||||
return OwningExprResult(Actions);
|
return OwningExprResult(Actions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -211,7 +211,7 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
|
||||||
if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
|
if (ExpectAndConsume(tok::less, diag::err_expected_less_after, CastName))
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
|
||||||
TypeTy *CastTy = ParseTypeName();
|
TypeResult CastTy = ParseTypeName();
|
||||||
SourceLocation RAngleBracketLoc = Tok.getLocation();
|
SourceLocation RAngleBracketLoc = Tok.getLocation();
|
||||||
|
|
||||||
if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
|
if (ExpectAndConsume(tok::greater, diag::err_expected_greater))
|
||||||
|
@ -224,9 +224,10 @@ Parser::OwningExprResult Parser::ParseCXXCasts() {
|
||||||
|
|
||||||
OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
|
OwningExprResult Result(ParseSimpleParenExpression(RParenLoc));
|
||||||
|
|
||||||
if (!Result.isInvalid())
|
if (!Result.isInvalid() && !CastTy.isInvalid())
|
||||||
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
|
Result = Actions.ActOnCXXNamedCast(OpLoc, Kind,
|
||||||
LAngleBracketLoc, CastTy, RAngleBracketLoc,
|
LAngleBracketLoc, CastTy.get(),
|
||||||
|
RAngleBracketLoc,
|
||||||
LParenLoc, Result.release(), RParenLoc);
|
LParenLoc, Result.release(), RParenLoc);
|
||||||
|
|
||||||
return move(Result);
|
return move(Result);
|
||||||
|
@ -253,16 +254,16 @@ Parser::OwningExprResult Parser::ParseCXXTypeid() {
|
||||||
OwningExprResult Result(Actions);
|
OwningExprResult Result(Actions);
|
||||||
|
|
||||||
if (isTypeIdInParens()) {
|
if (isTypeIdInParens()) {
|
||||||
TypeTy *Ty = ParseTypeName();
|
TypeResult Ty = ParseTypeName();
|
||||||
|
|
||||||
// Match the ')'.
|
// Match the ')'.
|
||||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
|
||||||
if (!Ty)
|
if (Ty.isInvalid())
|
||||||
return ExprError();
|
return ExprError();
|
||||||
|
|
||||||
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
|
Result = Actions.ActOnCXXTypeid(OpLoc, LParenLoc, /*isType=*/true,
|
||||||
Ty, RParenLoc);
|
Ty.get(), RParenLoc);
|
||||||
} else {
|
} else {
|
||||||
Result = ParseExpression();
|
Result = ParseExpression();
|
||||||
|
|
||||||
|
@ -919,9 +920,12 @@ Parser::OwningExprResult Parser::ParseUnaryTypeTrait()
|
||||||
// FIXME: Error reporting absolutely sucks! If the this fails to parse a type
|
// FIXME: Error reporting absolutely sucks! If the this fails to parse a type
|
||||||
// there will be cryptic errors about mismatched parentheses and missing
|
// there will be cryptic errors about mismatched parentheses and missing
|
||||||
// specifiers.
|
// specifiers.
|
||||||
TypeTy *Ty = ParseTypeName();
|
TypeResult Ty = ParseTypeName();
|
||||||
|
|
||||||
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
|
SourceLocation RParen = MatchRHSPunctuation(tok::r_paren, LParen);
|
||||||
|
|
||||||
return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty, RParen);
|
if (Ty.isInvalid())
|
||||||
|
return ExprError();
|
||||||
|
|
||||||
|
return Actions.ActOnUnaryTypeTrait(UTT, Loc, LParen, Ty.get(), RParen);
|
||||||
}
|
}
|
||||||
|
|
|
@ -629,8 +629,11 @@ Parser::TypeTy *Parser::ParseObjCTypeName(ObjCDeclSpec &DS) {
|
||||||
ParseObjCTypeQualifierList(DS);
|
ParseObjCTypeQualifierList(DS);
|
||||||
|
|
||||||
TypeTy *Ty = 0;
|
TypeTy *Ty = 0;
|
||||||
if (isTypeSpecifierQualifier())
|
if (isTypeSpecifierQualifier()) {
|
||||||
Ty = ParseTypeName();
|
TypeResult TypeSpec = ParseTypeName();
|
||||||
|
if (!TypeSpec.isInvalid())
|
||||||
|
Ty = TypeSpec.get();
|
||||||
|
}
|
||||||
|
|
||||||
if (Tok.is(tok::r_paren))
|
if (Tok.is(tok::r_paren))
|
||||||
ConsumeParen();
|
ConsumeParen();
|
||||||
|
@ -1627,12 +1630,15 @@ Parser::ParseObjCEncodeExpression(SourceLocation AtLoc) {
|
||||||
|
|
||||||
SourceLocation LParenLoc = ConsumeParen();
|
SourceLocation LParenLoc = ConsumeParen();
|
||||||
|
|
||||||
TypeTy *Ty = ParseTypeName();
|
TypeResult Ty = ParseTypeName();
|
||||||
|
|
||||||
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
SourceLocation RParenLoc = MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
|
||||||
return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc, Ty,
|
if (Ty.isInvalid())
|
||||||
RParenLoc));
|
return ExprError();
|
||||||
|
|
||||||
|
return Owned(Actions.ParseObjCEncodeExpression(AtLoc, EncLoc, LParenLoc,
|
||||||
|
Ty.get(), RParenLoc));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// objc-protocol-expression
|
/// objc-protocol-expression
|
||||||
|
|
|
@ -240,9 +240,10 @@ Parser::DeclTy *Parser::ParseTypeParameter(unsigned Depth, unsigned Position) {
|
||||||
if(Tok.is(tok::equal)) {
|
if(Tok.is(tok::equal)) {
|
||||||
SourceLocation EqualLoc = ConsumeToken();
|
SourceLocation EqualLoc = ConsumeToken();
|
||||||
SourceLocation DefaultLoc = Tok.getLocation();
|
SourceLocation DefaultLoc = Tok.getLocation();
|
||||||
if (TypeTy *DefaultType = ParseTypeName())
|
TypeResult DefaultType = ParseTypeName();
|
||||||
|
if (!DefaultType.isInvalid())
|
||||||
Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
|
Actions.ActOnTypeParameterDefault(TypeParam, EqualLoc, DefaultLoc,
|
||||||
DefaultType);
|
DefaultType.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
return TypeParam;
|
return TypeParam;
|
||||||
|
@ -529,7 +530,10 @@ void *Parser::ParseTemplateArgument(bool &ArgIsType) {
|
||||||
// Therefore, we initially try to parse a type-id.
|
// Therefore, we initially try to parse a type-id.
|
||||||
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
|
if (isCXXTypeId(TypeIdAsTemplateArgument)) {
|
||||||
ArgIsType = true;
|
ArgIsType = true;
|
||||||
return ParseTypeName();
|
TypeResult TypeArg = ParseTypeName();
|
||||||
|
if (TypeArg.isInvalid())
|
||||||
|
return 0;
|
||||||
|
return TypeArg.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
OwningExprResult ExprArg = ParseAssignmentExpression();
|
OwningExprResult ExprArg = ParseAssignmentExpression();
|
||||||
|
|
|
@ -29,7 +29,6 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
|
||||||
QualType Result;
|
QualType Result;
|
||||||
|
|
||||||
switch (DS.getTypeSpecType()) {
|
switch (DS.getTypeSpecType()) {
|
||||||
default: assert(0 && "Unknown TypeSpecType!");
|
|
||||||
case DeclSpec::TST_void:
|
case DeclSpec::TST_void:
|
||||||
Result = Context.VoidTy;
|
Result = Context.VoidTy;
|
||||||
break;
|
break;
|
||||||
|
@ -169,6 +168,8 @@ QualType Sema::ConvertDeclSpecToType(const DeclSpec &DS) {
|
||||||
Result = Context.getTypeOfExpr(E);
|
Result = Context.getTypeOfExpr(E);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case DeclSpec::TST_error:
|
||||||
|
return QualType();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle complex types.
|
// Handle complex types.
|
||||||
|
@ -277,8 +278,11 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S, unsigned Skip) {
|
||||||
// We default to a dependent type initially. Can be modified by
|
// We default to a dependent type initially. Can be modified by
|
||||||
// the first return statement.
|
// the first return statement.
|
||||||
T = Context.DependentTy;
|
T = Context.DependentTy;
|
||||||
else
|
else {
|
||||||
T = ConvertDeclSpecToType(DS);
|
T = ConvertDeclSpecToType(DS);
|
||||||
|
if (T.isNull())
|
||||||
|
return T;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,16 +729,13 @@ Sema::TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) {
|
||||||
assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
|
assert(D.getIdentifier() == 0 && "Type name should have no identifier!");
|
||||||
|
|
||||||
QualType T = GetTypeForDeclarator(D, S);
|
QualType T = GetTypeForDeclarator(D, S);
|
||||||
|
if (T.isNull())
|
||||||
assert(!T.isNull() && "GetTypeForDeclarator() returned null type");
|
return true;
|
||||||
|
|
||||||
// Check that there are no default arguments (C++ only).
|
// Check that there are no default arguments (C++ only).
|
||||||
if (getLangOptions().CPlusPlus)
|
if (getLangOptions().CPlusPlus)
|
||||||
CheckExtraCXXDefaultArguments(D);
|
CheckExtraCXXDefaultArguments(D);
|
||||||
|
|
||||||
// In this context, we *do not* check D.getInvalidType(). If the declarator
|
|
||||||
// type was invalid, GetTypeForDeclarator() still returns a "valid" type,
|
|
||||||
// though it will not reflect the user specified type.
|
|
||||||
return T.getAsOpaquePtr();
|
return T.getAsOpaquePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче