mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-29 13:36:09 +00:00
-Add support for cv-qualifiers after function declarators.
-Add withConst/withVolatile/withRestrict methods to QualType class, that return the QualType plus the respective qualifier. llvm-svn: 58120
This commit is contained in:
parent
c157586598
commit
22c40fa285
@ -208,7 +208,8 @@ public:
|
|||||||
/// getFunctionType - Return a normal function type with a typed argument
|
/// getFunctionType - Return a normal function type with a typed argument
|
||||||
/// list. isVariadic indicates whether the argument list includes '...'.
|
/// list. isVariadic indicates whether the argument list includes '...'.
|
||||||
QualType getFunctionType(QualType ResultTy, const QualType *ArgArray,
|
QualType getFunctionType(QualType ResultTy, const QualType *ArgArray,
|
||||||
unsigned NumArgs, bool isVariadic);
|
unsigned NumArgs, bool isVariadic,
|
||||||
|
unsigned TypeQuals = 0);
|
||||||
|
|
||||||
/// getTypeDeclType - Return the unique reference to the type for
|
/// getTypeDeclType - Return the unique reference to the type for
|
||||||
/// the specified type declaration.
|
/// the specified type declaration.
|
||||||
|
@ -230,6 +230,10 @@ public:
|
|||||||
/// Should only be called for instance methods.
|
/// Should only be called for instance methods.
|
||||||
QualType getThisType(ASTContext &C) const;
|
QualType getThisType(ASTContext &C) const;
|
||||||
|
|
||||||
|
unsigned getTypeQualifiers() const {
|
||||||
|
return getType()->getAsFunctionTypeProto()->getTypeQuals();
|
||||||
|
}
|
||||||
|
|
||||||
// Implement isa/cast/dyncast/etc.
|
// Implement isa/cast/dyncast/etc.
|
||||||
static bool classof(const Decl *D) { return D->getKind() == CXXMethod; }
|
static bool classof(const Decl *D) { return D->getKind() == CXXMethod; }
|
||||||
static bool classof(const CXXMethodDecl *D) { return true; }
|
static bool classof(const CXXMethodDecl *D) { return true; }
|
||||||
|
@ -158,6 +158,10 @@ public:
|
|||||||
return QualType(getTypePtr(), TQs|getCVRQualifiers());
|
return QualType(getTypePtr(), TQs|getCVRQualifiers());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QualType withConst() const { return getWithAdditionalQualifiers(Const); }
|
||||||
|
QualType withVolatile() const { return getWithAdditionalQualifiers(Volatile);}
|
||||||
|
QualType withRestrict() const { return getWithAdditionalQualifiers(Restrict);}
|
||||||
|
|
||||||
QualType getUnqualifiedType() const;
|
QualType getUnqualifiedType() const;
|
||||||
bool isMoreQualifiedThan(QualType Other) const;
|
bool isMoreQualifiedThan(QualType Other) const;
|
||||||
bool isAtLeastAsQualifiedAs(QualType Other) const;
|
bool isAtLeastAsQualifiedAs(QualType Other) const;
|
||||||
@ -918,12 +922,24 @@ class FunctionType : public Type {
|
|||||||
/// tightly with the ivars in Type.
|
/// tightly with the ivars in Type.
|
||||||
bool SubClassData : 1;
|
bool SubClassData : 1;
|
||||||
|
|
||||||
|
/// TypeQuals - Used only by FunctionTypeProto, put here to pack with the
|
||||||
|
/// other bitfields.
|
||||||
|
/// The qualifiers are part of FunctionTypeProto because...
|
||||||
|
///
|
||||||
|
/// C++ 8.3.5p4: The return type, the parameter type list and the
|
||||||
|
/// cv-qualifier-seq, [...], are part of the function type.
|
||||||
|
///
|
||||||
|
unsigned TypeQuals : 3;
|
||||||
|
|
||||||
// The type returned by the function.
|
// The type returned by the function.
|
||||||
QualType ResultType;
|
QualType ResultType;
|
||||||
protected:
|
protected:
|
||||||
FunctionType(TypeClass tc, QualType res, bool SubclassInfo,QualType Canonical)
|
FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
|
||||||
: Type(tc, Canonical), SubClassData(SubclassInfo), ResultType(res) {}
|
unsigned typeQuals, QualType Canonical)
|
||||||
|
: Type(tc, Canonical),
|
||||||
|
SubClassData(SubclassInfo), TypeQuals(typeQuals), ResultType(res) {}
|
||||||
bool getSubClassData() const { return SubClassData; }
|
bool getSubClassData() const { return SubClassData; }
|
||||||
|
unsigned getTypeQuals() const { return TypeQuals; }
|
||||||
public:
|
public:
|
||||||
|
|
||||||
QualType getResultType() const { return ResultType; }
|
QualType getResultType() const { return ResultType; }
|
||||||
@ -940,7 +956,7 @@ public:
|
|||||||
/// no information available about its arguments.
|
/// no information available about its arguments.
|
||||||
class FunctionTypeNoProto : public FunctionType, public llvm::FoldingSetNode {
|
class FunctionTypeNoProto : public FunctionType, public llvm::FoldingSetNode {
|
||||||
FunctionTypeNoProto(QualType Result, QualType Canonical)
|
FunctionTypeNoProto(QualType Result, QualType Canonical)
|
||||||
: FunctionType(FunctionNoProto, Result, false, Canonical) {}
|
: FunctionType(FunctionNoProto, Result, false, 0, Canonical) {}
|
||||||
friend class ASTContext; // ASTContext creates these.
|
friend class ASTContext; // ASTContext creates these.
|
||||||
public:
|
public:
|
||||||
// No additional state past what FunctionType provides.
|
// No additional state past what FunctionType provides.
|
||||||
@ -970,8 +986,8 @@ protected:
|
|||||||
/// arguments, not as having a single void argument.
|
/// arguments, not as having a single void argument.
|
||||||
class FunctionTypeProto : public FunctionType, public llvm::FoldingSetNode {
|
class FunctionTypeProto : public FunctionType, public llvm::FoldingSetNode {
|
||||||
FunctionTypeProto(QualType Result, const QualType *ArgArray, unsigned numArgs,
|
FunctionTypeProto(QualType Result, const QualType *ArgArray, unsigned numArgs,
|
||||||
bool isVariadic, QualType Canonical)
|
bool isVariadic, unsigned typeQuals, QualType Canonical)
|
||||||
: FunctionType(FunctionProto, Result, isVariadic, Canonical),
|
: FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical),
|
||||||
NumArgs(numArgs) {
|
NumArgs(numArgs) {
|
||||||
// Fill in the trailing argument array.
|
// Fill in the trailing argument array.
|
||||||
QualType *ArgInfo = reinterpret_cast<QualType *>(this+1);;
|
QualType *ArgInfo = reinterpret_cast<QualType *>(this+1);;
|
||||||
@ -996,6 +1012,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool isVariadic() const { return getSubClassData(); }
|
bool isVariadic() const { return getSubClassData(); }
|
||||||
|
unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
|
||||||
|
|
||||||
typedef const QualType *arg_type_iterator;
|
typedef const QualType *arg_type_iterator;
|
||||||
arg_type_iterator arg_type_begin() const {
|
arg_type_iterator arg_type_begin() const {
|
||||||
@ -1013,7 +1030,7 @@ public:
|
|||||||
void Profile(llvm::FoldingSetNodeID &ID);
|
void Profile(llvm::FoldingSetNodeID &ID);
|
||||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
|
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
|
||||||
arg_type_iterator ArgTys, unsigned NumArgs,
|
arg_type_iterator ArgTys, unsigned NumArgs,
|
||||||
bool isVariadic);
|
bool isVariadic, unsigned TypeQuals);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void EmitImpl(llvm::Serializer& S) const;
|
virtual void EmitImpl(llvm::Serializer& S) const;
|
||||||
|
@ -1041,6 +1041,11 @@ DIAG(err_invalid_this_use, ERROR,
|
|||||||
"invalid use of 'this' outside of a nonstatic member function")
|
"invalid use of 'this' outside of a nonstatic member function")
|
||||||
DIAG(err_invalid_member_use_in_static_method, ERROR,
|
DIAG(err_invalid_member_use_in_static_method, ERROR,
|
||||||
"invalid use of member '%0' in static member function")
|
"invalid use of member '%0' in static member function")
|
||||||
|
DIAG(err_invalid_qualified_function_type, ERROR,
|
||||||
|
"type qualifier is not allowed on this function")
|
||||||
|
DIAG(err_invalid_qualified_typedef_function_type_use, ERROR,
|
||||||
|
"a qualified function type cannot be used to declare a nonmember function "
|
||||||
|
"or a static member function")
|
||||||
DIAG(err_invalid_non_static_member_use, ERROR,
|
DIAG(err_invalid_non_static_member_use, ERROR,
|
||||||
"invalid use of nonstatic data member '%0'")
|
"invalid use of nonstatic data member '%0'")
|
||||||
DIAG(err_invalid_incomplete_type_use, ERROR,
|
DIAG(err_invalid_incomplete_type_use, ERROR,
|
||||||
|
@ -442,6 +442,10 @@ struct DeclaratorChunk {
|
|||||||
/// with ',...)', this is true.
|
/// with ',...)', this is true.
|
||||||
bool isVariadic : 1;
|
bool isVariadic : 1;
|
||||||
|
|
||||||
|
/// The type qualifiers: const/volatile/restrict.
|
||||||
|
/// The qualifier bitmask values are the same as in QualType.
|
||||||
|
unsigned TypeQuals : 3;
|
||||||
|
|
||||||
/// NumArgs - This is the number of formal arguments provided for the
|
/// NumArgs - This is the number of formal arguments provided for the
|
||||||
/// declarator.
|
/// declarator.
|
||||||
unsigned NumArgs;
|
unsigned NumArgs;
|
||||||
@ -528,12 +532,13 @@ struct DeclaratorChunk {
|
|||||||
/// getFunction - Return a DeclaratorChunk for a function.
|
/// getFunction - Return a DeclaratorChunk for a function.
|
||||||
static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
|
static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
|
||||||
ParamInfo *ArgInfo, unsigned NumArgs,
|
ParamInfo *ArgInfo, unsigned NumArgs,
|
||||||
SourceLocation Loc) {
|
unsigned TypeQuals, SourceLocation Loc) {
|
||||||
DeclaratorChunk I;
|
DeclaratorChunk I;
|
||||||
I.Kind = Function;
|
I.Kind = Function;
|
||||||
I.Loc = Loc;
|
I.Loc = Loc;
|
||||||
I.Fun.hasPrototype = hasProto;
|
I.Fun.hasPrototype = hasProto;
|
||||||
I.Fun.isVariadic = isVariadic;
|
I.Fun.isVariadic = isVariadic;
|
||||||
|
I.Fun.TypeQuals = TypeQuals;
|
||||||
I.Fun.NumArgs = NumArgs;
|
I.Fun.NumArgs = NumArgs;
|
||||||
I.Fun.ArgInfo = 0;
|
I.Fun.ArgInfo = 0;
|
||||||
|
|
||||||
|
@ -884,11 +884,13 @@ QualType ASTContext::getFunctionTypeNoProto(QualType ResultTy) {
|
|||||||
/// getFunctionType - Return a normal function type with a typed argument
|
/// getFunctionType - Return a normal function type with a typed argument
|
||||||
/// list. isVariadic indicates whether the argument list includes '...'.
|
/// list. isVariadic indicates whether the argument list includes '...'.
|
||||||
QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
||||||
unsigned NumArgs, bool isVariadic) {
|
unsigned NumArgs, bool isVariadic,
|
||||||
|
unsigned TypeQuals) {
|
||||||
// Unique functions, to guarantee there is only one function of a particular
|
// Unique functions, to guarantee there is only one function of a particular
|
||||||
// structure.
|
// structure.
|
||||||
llvm::FoldingSetNodeID ID;
|
llvm::FoldingSetNodeID ID;
|
||||||
FunctionTypeProto::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic);
|
FunctionTypeProto::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
|
||||||
|
TypeQuals);
|
||||||
|
|
||||||
void *InsertPos = 0;
|
void *InsertPos = 0;
|
||||||
if (FunctionTypeProto *FTP =
|
if (FunctionTypeProto *FTP =
|
||||||
@ -925,7 +927,7 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
|
|||||||
(FunctionTypeProto*)malloc(sizeof(FunctionTypeProto) +
|
(FunctionTypeProto*)malloc(sizeof(FunctionTypeProto) +
|
||||||
NumArgs*sizeof(QualType));
|
NumArgs*sizeof(QualType));
|
||||||
new (FTP) FunctionTypeProto(ResultTy, ArgArray, NumArgs, isVariadic,
|
new (FTP) FunctionTypeProto(ResultTy, ArgArray, NumArgs, isVariadic,
|
||||||
Canonical);
|
TypeQuals, Canonical);
|
||||||
Types.push_back(FTP);
|
Types.push_back(FTP);
|
||||||
FunctionTypeProtos.InsertNode(FTP, InsertPos);
|
FunctionTypeProtos.InsertNode(FTP, InsertPos);
|
||||||
return QualType(FTP, 0);
|
return QualType(FTP, 0);
|
||||||
|
@ -64,9 +64,8 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
|
|||||||
assert(isInstance() && "No 'this' for static methods!");
|
assert(isInstance() && "No 'this' for static methods!");
|
||||||
QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(
|
QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(
|
||||||
cast<CXXRecordDecl>(getParent())));
|
cast<CXXRecordDecl>(getParent())));
|
||||||
QualType ThisTy = C.getPointerType(ClassTy);
|
ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
|
||||||
ThisTy.addConst();
|
return C.getPointerType(ClassTy).withConst();
|
||||||
return ThisTy;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
|
||||||
|
@ -705,15 +705,18 @@ const char *BuiltinType::getName() const {
|
|||||||
|
|
||||||
void FunctionTypeProto::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
|
void FunctionTypeProto::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
|
||||||
arg_type_iterator ArgTys,
|
arg_type_iterator ArgTys,
|
||||||
unsigned NumArgs, bool isVariadic) {
|
unsigned NumArgs, bool isVariadic,
|
||||||
|
unsigned TypeQuals) {
|
||||||
ID.AddPointer(Result.getAsOpaquePtr());
|
ID.AddPointer(Result.getAsOpaquePtr());
|
||||||
for (unsigned i = 0; i != NumArgs; ++i)
|
for (unsigned i = 0; i != NumArgs; ++i)
|
||||||
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
|
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
|
||||||
ID.AddInteger(isVariadic);
|
ID.AddInteger(isVariadic);
|
||||||
|
ID.AddInteger(TypeQuals);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FunctionTypeProto::Profile(llvm::FoldingSetNodeID &ID) {
|
void FunctionTypeProto::Profile(llvm::FoldingSetNodeID &ID) {
|
||||||
Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic());
|
Profile(ID, getResultType(), arg_type_begin(), NumArgs, isVariadic(),
|
||||||
|
getTypeQuals());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
|
void ObjCQualifiedInterfaceType::Profile(llvm::FoldingSetNodeID &ID,
|
||||||
|
@ -1213,6 +1213,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D) {
|
|||||||
/// direct-declarator '(' identifier-list[opt] ')'
|
/// direct-declarator '(' identifier-list[opt] ')'
|
||||||
/// [GNU] direct-declarator '(' parameter-forward-declarations
|
/// [GNU] direct-declarator '(' parameter-forward-declarations
|
||||||
/// parameter-type-list[opt] ')'
|
/// parameter-type-list[opt] ')'
|
||||||
|
/// [C++] direct-declarator '(' parameter-declaration-clause ')'
|
||||||
|
/// cv-qualifier-seq[opt] exception-specification[opt]
|
||||||
///
|
///
|
||||||
void Parser::ParseDirectDeclarator(Declarator &D) {
|
void Parser::ParseDirectDeclarator(Declarator &D) {
|
||||||
// Parse the first direct-declarator seen.
|
// Parse the first direct-declarator seen.
|
||||||
@ -1371,6 +1373,9 @@ void Parser::ParseParenDeclarator(Declarator &D) {
|
|||||||
/// '=' assignment-expression
|
/// '=' assignment-expression
|
||||||
/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
|
/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
|
||||||
///
|
///
|
||||||
|
/// For C++, after the parameter-list, it also parses "cv-qualifier-seq[opt]"
|
||||||
|
/// and "exception-specification[opt]"(TODO).
|
||||||
|
///
|
||||||
void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
||||||
AttributeList *AttrList,
|
AttributeList *AttrList,
|
||||||
bool RequiresArg) {
|
bool RequiresArg) {
|
||||||
@ -1384,19 +1389,28 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
|||||||
delete AttrList;
|
delete AttrList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ConsumeParen(); // Eat the closing ')'.
|
||||||
|
|
||||||
|
// cv-qualifier-seq[opt].
|
||||||
|
DeclSpec DS;
|
||||||
|
if (getLang().CPlusPlus) {
|
||||||
|
ParseTypeQualifierListOpt(DS);
|
||||||
|
// FIXME: Parse exception-specification[opt].
|
||||||
|
}
|
||||||
|
|
||||||
// Remember that we parsed a function type, and remember the attributes.
|
// Remember that we parsed a function type, and remember the attributes.
|
||||||
// int() -> no prototype, no '...'.
|
// int() -> no prototype, no '...'.
|
||||||
D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/ false,
|
D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus,
|
||||||
/*variadic*/ false,
|
/*variadic*/ false,
|
||||||
/*arglist*/ 0, 0, LParenLoc));
|
/*arglist*/ 0, 0,
|
||||||
|
DS.getTypeQualifiers(),
|
||||||
ConsumeParen(); // Eat the closing ')'.
|
LParenLoc));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alternatively, this parameter list may be an identifier list form for a
|
// Alternatively, this parameter list may be an identifier list form for a
|
||||||
// K&R-style function: void foo(a,b,c)
|
// K&R-style function: void foo(a,b,c)
|
||||||
if (Tok.is(tok::identifier) &&
|
if (!getLang().CPlusPlus && Tok.is(tok::identifier) &&
|
||||||
// K&R identifier lists can't have typedefs as identifiers, per
|
// K&R identifier lists can't have typedefs as identifiers, per
|
||||||
// C99 6.7.5.3p11.
|
// C99 6.7.5.3p11.
|
||||||
!Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
|
!Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
|
||||||
@ -1508,13 +1522,21 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
|
|||||||
// Leave prototype scope.
|
// Leave prototype scope.
|
||||||
ExitScope();
|
ExitScope();
|
||||||
|
|
||||||
|
// If we have the closing ')', eat it.
|
||||||
|
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
|
||||||
|
// cv-qualifier-seq[opt].
|
||||||
|
DeclSpec DS;
|
||||||
|
if (getLang().CPlusPlus) {
|
||||||
|
ParseTypeQualifierListOpt(DS);
|
||||||
|
// FIXME: Parse exception-specification[opt].
|
||||||
|
}
|
||||||
|
|
||||||
// Remember that we parsed a function type, and remember the attributes.
|
// Remember that we parsed a function type, and remember the attributes.
|
||||||
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
|
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
|
||||||
&ParamInfo[0], ParamInfo.size(),
|
&ParamInfo[0], ParamInfo.size(),
|
||||||
|
DS.getTypeQualifiers(),
|
||||||
LParenLoc));
|
LParenLoc));
|
||||||
|
|
||||||
// If we have the closing ')', eat it and we're done.
|
|
||||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
|
/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
|
||||||
@ -1581,7 +1603,7 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
|
|||||||
// has no prototype.
|
// has no prototype.
|
||||||
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
|
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
|
||||||
&ParamInfo[0], ParamInfo.size(),
|
&ParamInfo[0], ParamInfo.size(),
|
||||||
LParenLoc));
|
/*TypeQuals*/0, LParenLoc));
|
||||||
|
|
||||||
// If we have the closing ')', eat it and we're done.
|
// If we have the closing ')', eat it and we're done.
|
||||||
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
MatchRHSPunctuation(tok::r_paren, LParenLoc);
|
||||||
|
@ -1116,7 +1116,7 @@ Parser::ExprResult Parser::ParseBlockLiteralExpression() {
|
|||||||
} else {
|
} else {
|
||||||
// Otherwise, pretend we saw (void).
|
// Otherwise, pretend we saw (void).
|
||||||
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
|
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
|
||||||
0, 0, CaretLoc));
|
0, 0, 0, CaretLoc));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inform sema that we are starting a block.
|
// Inform sema that we are starting a block.
|
||||||
|
@ -1820,7 +1820,7 @@ ScopedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
|
|||||||
Error = Error; // Silence warning.
|
Error = Error; // Silence warning.
|
||||||
assert(!Error && "Error setting up implicit decl!");
|
assert(!Error && "Error setting up implicit decl!");
|
||||||
Declarator D(DS, Declarator::BlockContext);
|
Declarator D(DS, Declarator::BlockContext);
|
||||||
D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, Loc));
|
D.AddTypeInfo(DeclaratorChunk::getFunction(false, false, 0, 0, 0, Loc));
|
||||||
D.SetIdentifier(&II, Loc);
|
D.SetIdentifier(&II, Loc);
|
||||||
|
|
||||||
// Insert this function into translation-unit scope.
|
// Insert this function into translation-unit scope.
|
||||||
|
@ -402,7 +402,9 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
|
|||||||
if (FD->isInvalidDecl())
|
if (FD->isInvalidDecl())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return new DeclRefExpr(FD, FD->getType(), Loc);
|
// FIXME: Handle 'mutable'.
|
||||||
|
return new DeclRefExpr(FD,
|
||||||
|
FD->getType().getWithAdditionalQualifiers(MD->getTypeQualifiers()),Loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Diag(Loc, diag::err_invalid_non_static_member_use, FD->getName());
|
return Diag(Loc, diag::err_invalid_non_static_member_use, FD->getName());
|
||||||
|
@ -409,7 +409,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
|
|||||||
if (getLangOptions().CPlusPlus) {
|
if (getLangOptions().CPlusPlus) {
|
||||||
// C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
|
// C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
|
||||||
// function takes no arguments.
|
// function takes no arguments.
|
||||||
T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic);
|
T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic,FTI.TypeQuals);
|
||||||
} else {
|
} else {
|
||||||
// Simple void foo(), where the incoming T is the result type.
|
// Simple void foo(), where the incoming T is the result type.
|
||||||
T = Context.getFunctionTypeNoProto(T);
|
T = Context.getFunctionTypeNoProto(T);
|
||||||
@ -482,7 +482,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
|
|||||||
ArgTys.push_back(ArgTy);
|
ArgTys.push_back(ArgTy);
|
||||||
}
|
}
|
||||||
T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
|
T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
|
||||||
FTI.isVariadic);
|
FTI.isVariadic, FTI.TypeQuals);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -492,6 +492,31 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
|
|||||||
ProcessTypeAttributeList(T, AL);
|
ProcessTypeAttributeList(T, AL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (getLangOptions().CPlusPlus && T->isFunctionType()) {
|
||||||
|
const FunctionTypeProto *FnTy = T->getAsFunctionTypeProto();
|
||||||
|
assert(FnTy && "Why oh why is there not a FunctionTypeProto here ?");
|
||||||
|
|
||||||
|
// C++ 8.3.5p4: A cv-qualifier-seq shall only be part of the function type
|
||||||
|
// for a nonstatic member function, the function type to which a pointer
|
||||||
|
// to member refers, or the top-level function type of a function typedef
|
||||||
|
// declaration.
|
||||||
|
if (FnTy->getTypeQuals() != 0 &&
|
||||||
|
D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef &&
|
||||||
|
(D.getContext() != Declarator::MemberContext ||
|
||||||
|
D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) {
|
||||||
|
|
||||||
|
if (D.isFunctionDeclarator())
|
||||||
|
Diag(D.getIdentifierLoc(), diag::err_invalid_qualified_function_type);
|
||||||
|
else
|
||||||
|
Diag(D.getIdentifierLoc(),
|
||||||
|
diag::err_invalid_qualified_typedef_function_type_use);
|
||||||
|
|
||||||
|
// Strip the cv-quals from the type.
|
||||||
|
T = Context.getFunctionType(FnTy->getResultType(), FnTy->arg_type_begin(),
|
||||||
|
FnTy->getNumArgs(), FnTy->isVariadic());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If there were any type attributes applied to the decl itself (not the
|
// If there were any type attributes applied to the decl itself (not the
|
||||||
// type, apply the type attribute to the type!)
|
// type, apply the type attribute to the type!)
|
||||||
if (const AttributeList *Attrs = D.getAttributes())
|
if (const AttributeList *Attrs = D.getAttributes())
|
||||||
|
23
clang/test/SemaCXX/function-type-qual.cpp
Normal file
23
clang/test/SemaCXX/function-type-qual.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
// RUN: clang -fsyntax-only -verify %s
|
||||||
|
|
||||||
|
void f() const; // expected-error {{type qualifier is not allowed on this function}}
|
||||||
|
|
||||||
|
typedef void cfn() const;
|
||||||
|
cfn f2; // expected-error {{a qualified function type cannot be used to declare a nonmember function or a static member function}}
|
||||||
|
|
||||||
|
class C {
|
||||||
|
void f() const;
|
||||||
|
cfn f2;
|
||||||
|
static void f3() const; // expected-error {{type qualifier is not allowed on this function}}
|
||||||
|
static cfn f4; // expected-error {{a qualified function type cannot be used to declare a nonmember function or a static member function}}
|
||||||
|
|
||||||
|
void m1() {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void m2() const {
|
||||||
|
x = 0; // expected-error {{read-only variable is not assignable}}
|
||||||
|
}
|
||||||
|
|
||||||
|
int x;
|
||||||
|
};
|
Loading…
x
Reference in New Issue
Block a user