summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-10-24 21:46:40 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2008-10-24 21:46:40 +0000
commit22c40fa28551f0da487f399a2fe0d3d25edf3edc (patch)
treebc2ce950d8e47e9a2ea3075d2d0ca232fb927385 /clang/lib
parentc15758659826d042658c2f8acc52a95d68741bb4 (diff)
downloadbcm5719-llvm-22c40fa28551f0da487f399a2fe0d3d25edf3edc.tar.gz
bcm5719-llvm-22c40fa28551f0da487f399a2fe0d3d25edf3edc.zip
-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
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp8
-rw-r--r--clang/lib/AST/DeclCXX.cpp5
-rw-r--r--clang/lib/AST/Type.cpp7
-rw-r--r--clang/lib/Parse/ParseDecl.cpp42
-rw-r--r--clang/lib/Parse/ParseExpr.cpp2
-rw-r--r--clang/lib/Sema/SemaDecl.cpp2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp4
-rw-r--r--clang/lib/Sema/SemaType.cpp29
8 files changed, 76 insertions, 23 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 75c58880486..f8129969b7b 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -884,11 +884,13 @@ QualType ASTContext::getFunctionTypeNoProto(QualType ResultTy) {
/// 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 @@ QualType ASTContext::getFunctionType(QualType ResultTy,const QualType *ArgArray,
(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);
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index 8baf4196bf6..a62ebad3651 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -64,9 +64,8 @@ QualType CXXMethodDecl::getThisType(ASTContext &C) const {
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,
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 5de44762c39..87b91ae2ea9 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -705,15 +705,18 @@ const char *BuiltinType::getName() const {
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,
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 27133d683c9..6bcb90b8ae6 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -1213,6 +1213,8 @@ void Parser::ParseDeclaratorInternal(Declarator &D) {
/// 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 @@ void Parser::ParseParenDeclarator(Declarator &D) {
/// '=' 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 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
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 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D,
// 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 @@ void Parser::ParseFunctionDeclaratorIdentifierList(SourceLocation LParenLoc,
// 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);
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index f6d7037ad12..7ab9d869c2d 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1116,7 +1116,7 @@ Parser::ExprResult Parser::ParseBlockLiteralExpression() {
} 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.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 4c36b09af80..c83c4def467 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -1820,7 +1820,7 @@ ScopedDecl *Sema::ImplicitlyDefineFunction(SourceLocation Loc,
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.
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 9b1543f7901..6fd1c5cc2fd 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -402,7 +402,9 @@ Sema::ExprResult Sema::ActOnIdentifierExpr(Scope *S, SourceLocation Loc,
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());
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index a12ec3ad7c8..7bcd1e5765f 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -409,7 +409,7 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
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 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
ArgTys.push_back(ArgTy);
}
T = Context.getFunctionType(T, &ArgTys[0], ArgTys.size(),
- FTI.isVariadic);
+ FTI.isVariadic, FTI.TypeQuals);
}
break;
}
@@ -491,6 +491,31 @@ QualType Sema::GetTypeForDeclarator(Declarator &D, Scope *S) {
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!)
OpenPOWER on IntegriCloud