[cfe-commits] r58120 - in /cfe/trunk: include/clang/AST/ASTContext.h include/clang/AST/DeclCXX.h include/clang/AST/Type.h include/clang/Basic/DiagnosticKinds.def include/clang/Parse/DeclSpec.h lib/AST/ASTContext.cpp lib/AST/DeclCXX.cpp lib/AST/Type.cpp lib/Parse/ParseDecl.cpp lib/Parse/ParseExpr.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp lib/Sema/SemaType.cpp test/SemaCXX/function-type-qual.cpp
Argiris Kirtzidis
akyrtzi at gmail.com
Fri Oct 24 14:46:40 PDT 2008
Author: akirtzidis
Date: Fri Oct 24 16:46:40 2008
New Revision: 58120
URL: http://llvm.org/viewvc/llvm-project?rev=58120&view=rev
Log:
-Add support for cv-qualifiers after function declarators.
-Add withConst/withVolatile/withRestrict methods to QualType class, that return the QualType plus the respective qualifier.
Added:
cfe/trunk/test/SemaCXX/function-type-qual.cpp
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/DeclCXX.h
cfe/trunk/include/clang/AST/Type.h
cfe/trunk/include/clang/Basic/DiagnosticKinds.def
cfe/trunk/include/clang/Parse/DeclSpec.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/DeclCXX.cpp
cfe/trunk/lib/AST/Type.cpp
cfe/trunk/lib/Parse/ParseDecl.cpp
cfe/trunk/lib/Parse/ParseExpr.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaType.cpp
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Fri Oct 24 16:46:40 2008
@@ -208,7 +208,8 @@
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
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
/// the specified type declaration.
Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Fri Oct 24 16:46:40 2008
@@ -230,6 +230,10 @@
/// Should only be called for instance methods.
QualType getThisType(ASTContext &C) const;
+ unsigned getTypeQualifiers() const {
+ return getType()->getAsFunctionTypeProto()->getTypeQuals();
+ }
+
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return D->getKind() == CXXMethod; }
static bool classof(const CXXMethodDecl *D) { return true; }
Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Fri Oct 24 16:46:40 2008
@@ -157,6 +157,10 @@
QualType getWithAdditionalQualifiers(unsigned TQs) const {
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;
bool isMoreQualifiedThan(QualType Other) const;
@@ -917,13 +921,25 @@
/// SubClassData - This field is owned by the subclass, put here to pack
/// tightly with the ivars in Type.
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.
QualType ResultType;
protected:
- FunctionType(TypeClass tc, QualType res, bool SubclassInfo,QualType Canonical)
- : Type(tc, Canonical), SubClassData(SubclassInfo), ResultType(res) {}
+ FunctionType(TypeClass tc, QualType res, bool SubclassInfo,
+ unsigned typeQuals, QualType Canonical)
+ : Type(tc, Canonical),
+ SubClassData(SubclassInfo), TypeQuals(typeQuals), ResultType(res) {}
bool getSubClassData() const { return SubClassData; }
+ unsigned getTypeQuals() const { return TypeQuals; }
public:
QualType getResultType() const { return ResultType; }
@@ -940,7 +956,7 @@
/// no information available about its arguments.
class FunctionTypeNoProto : public FunctionType, public llvm::FoldingSetNode {
FunctionTypeNoProto(QualType Result, QualType Canonical)
- : FunctionType(FunctionNoProto, Result, false, Canonical) {}
+ : FunctionType(FunctionNoProto, Result, false, 0, Canonical) {}
friend class ASTContext; // ASTContext creates these.
public:
// No additional state past what FunctionType provides.
@@ -970,8 +986,8 @@
/// arguments, not as having a single void argument.
class FunctionTypeProto : public FunctionType, public llvm::FoldingSetNode {
FunctionTypeProto(QualType Result, const QualType *ArgArray, unsigned numArgs,
- bool isVariadic, QualType Canonical)
- : FunctionType(FunctionProto, Result, isVariadic, Canonical),
+ bool isVariadic, unsigned typeQuals, QualType Canonical)
+ : FunctionType(FunctionProto, Result, isVariadic, typeQuals, Canonical),
NumArgs(numArgs) {
// Fill in the trailing argument array.
QualType *ArgInfo = reinterpret_cast<QualType *>(this+1);;
@@ -996,6 +1012,7 @@
}
bool isVariadic() const { return getSubClassData(); }
+ unsigned getTypeQuals() const { return FunctionType::getTypeQuals(); }
typedef const QualType *arg_type_iterator;
arg_type_iterator arg_type_begin() const {
@@ -1013,7 +1030,7 @@
void Profile(llvm::FoldingSetNodeID &ID);
static void Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys, unsigned NumArgs,
- bool isVariadic);
+ bool isVariadic, unsigned TypeQuals);
protected:
virtual void EmitImpl(llvm::Serializer& S) const;
Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Fri Oct 24 16:46:40 2008
@@ -1041,6 +1041,11 @@
"invalid use of 'this' outside of a nonstatic member function")
DIAG(err_invalid_member_use_in_static_method, ERROR,
"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,
"invalid use of nonstatic data member '%0'")
DIAG(err_invalid_incomplete_type_use, ERROR,
Modified: cfe/trunk/include/clang/Parse/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/DeclSpec.h?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Parse/DeclSpec.h Fri Oct 24 16:46:40 2008
@@ -442,6 +442,10 @@
/// with ',...)', this is true.
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
/// declarator.
unsigned NumArgs;
@@ -528,12 +532,13 @@
/// getFunction - Return a DeclaratorChunk for a function.
static DeclaratorChunk getFunction(bool hasProto, bool isVariadic,
ParamInfo *ArgInfo, unsigned NumArgs,
- SourceLocation Loc) {
+ unsigned TypeQuals, SourceLocation Loc) {
DeclaratorChunk I;
I.Kind = Function;
I.Loc = Loc;
I.Fun.hasPrototype = hasProto;
I.Fun.isVariadic = isVariadic;
+ I.Fun.TypeQuals = TypeQuals;
I.Fun.NumArgs = NumArgs;
I.Fun.ArgInfo = 0;
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Fri Oct 24 16:46:40 2008
@@ -884,11 +884,13 @@
/// getFunctionType - Return a normal function type with a typed argument
/// list. isVariadic indicates whether the argument list includes '...'.
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
// structure.
llvm::FoldingSetNodeID ID;
- FunctionTypeProto::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic);
+ FunctionTypeProto::Profile(ID, ResultTy, ArgArray, NumArgs, isVariadic,
+ TypeQuals);
void *InsertPos = 0;
if (FunctionTypeProto *FTP =
@@ -925,7 +927,7 @@
(FunctionTypeProto*)malloc(sizeof(FunctionTypeProto) +
NumArgs*sizeof(QualType));
new (FTP) FunctionTypeProto(ResultTy, ArgArray, NumArgs, isVariadic,
- Canonical);
+ TypeQuals, Canonical);
Types.push_back(FTP);
FunctionTypeProtos.InsertNode(FTP, InsertPos);
return QualType(FTP, 0);
Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Oct 24 16:46:40 2008
@@ -64,9 +64,8 @@
assert(isInstance() && "No 'this' for static methods!");
QualType ClassTy = C.getTagDeclType(const_cast<CXXRecordDecl*>(
cast<CXXRecordDecl>(getParent())));
- QualType ThisTy = C.getPointerType(ClassTy);
- ThisTy.addConst();
- return ThisTy;
+ ClassTy = ClassTy.getWithAdditionalQualifiers(getTypeQualifiers());
+ return C.getPointerType(ClassTy).withConst();
}
CXXClassVarDecl *CXXClassVarDecl::Create(ASTContext &C, CXXRecordDecl *RD,
Modified: cfe/trunk/lib/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Type.cpp (original)
+++ cfe/trunk/lib/AST/Type.cpp Fri Oct 24 16:46:40 2008
@@ -705,15 +705,18 @@
void FunctionTypeProto::Profile(llvm::FoldingSetNodeID &ID, QualType Result,
arg_type_iterator ArgTys,
- unsigned NumArgs, bool isVariadic) {
+ unsigned NumArgs, bool isVariadic,
+ unsigned TypeQuals) {
ID.AddPointer(Result.getAsOpaquePtr());
for (unsigned i = 0; i != NumArgs; ++i)
ID.AddPointer(ArgTys[i].getAsOpaquePtr());
ID.AddInteger(isVariadic);
+ ID.AddInteger(TypeQuals);
}
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,
Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Fri Oct 24 16:46:40 2008
@@ -1213,6 +1213,8 @@
/// direct-declarator '(' identifier-list[opt] ')'
/// [GNU] direct-declarator '(' parameter-forward-declarations
/// parameter-type-list[opt] ')'
+/// [C++] direct-declarator '(' parameter-declaration-clause ')'
+/// cv-qualifier-seq[opt] exception-specification[opt]
///
void Parser::ParseDirectDeclarator(Declarator &D) {
// Parse the first direct-declarator seen.
@@ -1371,6 +1373,9 @@
/// '=' assignment-expression
/// [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,
AttributeList *AttrList,
bool RequiresArg) {
@@ -1383,20 +1388,29 @@
Diag(Tok.getLocation(), diag::err_argument_required_after_attribute);
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.
// int() -> no prototype, no '...'.
- D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/ false,
+ D.AddTypeInfo(DeclaratorChunk::getFunction(/*prototype*/getLang().CPlusPlus,
/*variadic*/ false,
- /*arglist*/ 0, 0, LParenLoc));
-
- ConsumeParen(); // Eat the closing ')'.
+ /*arglist*/ 0, 0,
+ DS.getTypeQualifiers(),
+ LParenLoc));
return;
}
// Alternatively, this parameter list may be an identifier list form for a
// 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
// C99 6.7.5.3p11.
!Actions.isTypeName(*Tok.getIdentifierInfo(), CurScope)) {
@@ -1508,13 +1522,21 @@
// Leave prototype scope.
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.
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/true, IsVariadic,
&ParamInfo[0], ParamInfo.size(),
+ DS.getTypeQualifiers(),
LParenLoc));
-
- // If we have the closing ')', eat it and we're done.
- MatchRHSPunctuation(tok::r_paren, LParenLoc);
}
/// ParseFunctionDeclaratorIdentifierList - While parsing a function declarator
@@ -1581,7 +1603,7 @@
// has no prototype.
D.AddTypeInfo(DeclaratorChunk::getFunction(/*proto*/false, /*varargs*/false,
&ParamInfo[0], ParamInfo.size(),
- LParenLoc));
+ /*TypeQuals*/0, LParenLoc));
// If we have the closing ')', eat it and we're done.
MatchRHSPunctuation(tok::r_paren, LParenLoc);
Modified: cfe/trunk/lib/Parse/ParseExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExpr.cpp?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExpr.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExpr.cpp Fri Oct 24 16:46:40 2008
@@ -1116,7 +1116,7 @@
} else {
// Otherwise, pretend we saw (void).
ParamInfo.AddTypeInfo(DeclaratorChunk::getFunction(true, false,
- 0, 0, CaretLoc));
+ 0, 0, 0, CaretLoc));
}
// Inform sema that we are starting a block.
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Oct 24 16:46:40 2008
@@ -1820,7 +1820,7 @@
Error = Error; // Silence warning.
assert(!Error && "Error setting up implicit decl!");
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);
// Insert this function into translation-unit scope.
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Oct 24 16:46:40 2008
@@ -402,7 +402,9 @@
if (FD->isInvalidDecl())
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());
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=58120&r1=58119&r2=58120&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Fri Oct 24 16:46:40 2008
@@ -409,7 +409,7 @@
if (getLangOptions().CPlusPlus) {
// C++ 8.3.5p2: If the parameter-declaration-clause is empty, the
// function takes no arguments.
- T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic);
+ T = Context.getFunctionType(T, NULL, 0, FTI.isVariadic,FTI.TypeQuals);
} else {
// Simple void foo(), where the incoming T is the result type.
T = Context.getFunctionTypeNoProto(T);
@@ -482,7 +482,7 @@
ArgTys.push_back(ArgTy);
}
T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
- FTI.isVariadic);
+ FTI.isVariadic, FTI.TypeQuals);
}
break;
}
@@ -491,6 +491,31 @@
if (const AttributeList *AL = DeclType.getAttrs())
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
// type, apply the type attribute to the type!)
Added: cfe/trunk/test/SemaCXX/function-type-qual.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/function-type-qual.cpp?rev=58120&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/function-type-qual.cpp (added)
+++ cfe/trunk/test/SemaCXX/function-type-qual.cpp Fri Oct 24 16:46:40 2008
@@ -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;
+};
More information about the cfe-commits
mailing list