[cfe-commits] r105466 - in /cfe/trunk: include/clang/AST/Decl.h lib/Frontend/PCHReaderDecl.cpp lib/Frontend/PCHWriterDecl.cpp lib/Sema/Sema.h lib/Sema/SemaDecl.cpp lib/Sema/SemaExpr.cpp
John McCall
rjmccall at apple.com
Fri Jun 4 04:21:44 PDT 2010
Author: rjmccall
Date: Fri Jun 4 06:21:44 2010
New Revision: 105466
URL: http://llvm.org/viewvc/llvm-project?rev=105466&view=rev
Log:
Restructure how we interpret block-literal declarators. Correctly handle
the case where we pick up block arguments from a typedef. Save the block
signature as it was written, and preserve same through PCH.
Modified:
cfe/trunk/include/clang/AST/Decl.h
cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExpr.cpp
Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=105466&r1=105465&r2=105466&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Jun 4 06:21:44 2010
@@ -2127,11 +2127,13 @@
unsigned NumParams;
Stmt *Body;
+ TypeSourceInfo *SignatureAsWritten;
protected:
BlockDecl(DeclContext *DC, SourceLocation CaretLoc)
: Decl(Block, DC, CaretLoc), DeclContext(Block),
- IsVariadic(false), ParamInfo(0), NumParams(0), Body(0) {}
+ IsVariadic(false), ParamInfo(0), NumParams(0), Body(0),
+ SignatureAsWritten(0) {}
virtual ~BlockDecl();
virtual void Destroy(ASTContext& C);
@@ -2148,6 +2150,9 @@
Stmt *getBody() const { return (Stmt*) Body; }
void setBody(CompoundStmt *B) { Body = (Stmt*) B; }
+ void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; }
+ TypeSourceInfo *getSignatureAsWritten() const { return SignatureAsWritten; }
+
// Iterator access to formal parameters.
unsigned param_size() const { return getNumParams(); }
typedef ParmVarDecl **param_iterator;
Modified: cfe/trunk/lib/Frontend/PCHReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReaderDecl.cpp?rev=105466&r1=105465&r2=105466&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHReaderDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReaderDecl.cpp Fri Jun 4 06:21:44 2010
@@ -462,6 +462,7 @@
void PCHDeclReader::VisitBlockDecl(BlockDecl *BD) {
VisitDecl(BD);
BD->setBody(cast_or_null<CompoundStmt>(Reader.ReadDeclStmt()));
+ BD->setSignatureAsWritten(Reader.GetTypeSourceInfo(Record, Idx));
unsigned NumParams = Record[Idx++];
llvm::SmallVector<ParmVarDecl *, 16> Params;
Params.reserve(NumParams);
Modified: cfe/trunk/lib/Frontend/PCHWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriterDecl.cpp?rev=105466&r1=105465&r2=105466&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Jun 4 06:21:44 2010
@@ -471,6 +471,7 @@
void PCHDeclWriter::VisitBlockDecl(BlockDecl *D) {
VisitDecl(D);
Writer.AddStmt(D->getBody());
+ Writer.AddTypeSourceInfo(D->getSignatureAsWritten(), Record);
Record.push_back(D->param_size());
for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end();
P != PEnd; ++P)
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=105466&r1=105465&r2=105466&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Jun 4 06:21:44 2010
@@ -841,6 +841,9 @@
bool &OverloadableAttrRequired);
void CheckMain(FunctionDecl *FD);
virtual DeclPtrTy ActOnParamDeclarator(Scope *S, Declarator &D);
+ ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T);
ParmVarDecl *CheckParameter(DeclContext *DC,
TypeSourceInfo *TSInfo, QualType T,
IdentifierInfo *Name,
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=105466&r1=105465&r2=105466&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Jun 4 06:21:44 2010
@@ -3272,14 +3272,8 @@
// Synthesize a parameter for each argument type.
for (FunctionProtoType::arg_type_iterator AI = FT->arg_type_begin(),
AE = FT->arg_type_end(); AI != AE; ++AI) {
- ParmVarDecl *Param = ParmVarDecl::Create(Context, NewFD,
- D.getIdentifierLoc(), 0,
- *AI,
- Context.getTrivialTypeSourceInfo(*AI,
- D.getIdentifierLoc()),
- VarDecl::None,
- VarDecl::None, 0);
- Param->setImplicit();
+ ParmVarDecl *Param =
+ BuildParmVarDeclForTypedef(NewFD, D.getIdentifierLoc(), *AI);
Params.push_back(Param);
}
} else {
@@ -4331,6 +4325,18 @@
return DeclPtrTy::make(New);
}
+/// \brief Synthesizes a variable for a parameter arising from a
+/// typedef.
+ParmVarDecl *Sema::BuildParmVarDeclForTypedef(DeclContext *DC,
+ SourceLocation Loc,
+ QualType T) {
+ ParmVarDecl *Param = ParmVarDecl::Create(Context, DC, Loc, 0,
+ T, Context.getTrivialTypeSourceInfo(T, Loc),
+ VarDecl::None, VarDecl::None, 0);
+ Param->setImplicit();
+ return Param;
+}
+
ParmVarDecl *Sema::CheckParameter(DeclContext *DC,
TypeSourceInfo *TSInfo, QualType T,
IdentifierInfo *Name,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=105466&r1=105465&r2=105466&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Fri Jun 4 06:21:44 2010
@@ -6976,62 +6976,47 @@
assert(ParamInfo.getIdentifier()==0 && "block-id should have no identifier!");
BlockScopeInfo *CurBlock = getCurBlock();
- if (ParamInfo.getNumTypeObjects() == 0
- || ParamInfo.getTypeObject(0).Kind != DeclaratorChunk::Function) {
- ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
- QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
-
- if (T->isArrayType()) {
- Diag(ParamInfo.getSourceRange().getBegin(),
- diag::err_block_returns_array);
- return;
- }
-
- // The parameter list is optional, if there was none, assume ().
- if (!T->isFunctionType())
- T = Context.getFunctionType(T, 0, 0, false, 0, false, false, 0, 0,
- FunctionType::ExtInfo());
-
+ TypeSourceInfo *Sig = 0;
+ QualType T = GetTypeForDeclarator(ParamInfo, CurScope, &Sig);
+ CurBlock->TheDecl->setSignatureAsWritten(Sig);
+
+ QualType RetTy;
+ if (const FunctionType *Fn = T->getAs<FunctionType>()) {
+ RetTy = Fn->getResultType();
+ CurBlock->hasPrototype = isa<FunctionProtoType>(Fn);
+ CurBlock->isVariadic =
+ !isa<FunctionProtoType>(Fn) || cast<FunctionProtoType>(Fn)->isVariadic();
+ } else {
+ RetTy = T;
CurBlock->hasPrototype = true;
CurBlock->isVariadic = false;
- // Check for a valid sentinel attribute on this block.
- if (CurBlock->TheDecl->getAttr<SentinelAttr>()) {
- Diag(ParamInfo.getAttributes()->getLoc(),
- diag::warn_attribute_sentinel_not_variadic) << 1;
- // FIXME: remove the attribute.
- }
- QualType RetTy = T.getTypePtr()->getAs<FunctionType>()->getResultType();
-
- // Do not allow returning a objc interface by-value.
- if (RetTy->isObjCObjectType()) {
- Diag(ParamInfo.getSourceRange().getBegin(),
- diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
- return;
- }
+ }
- CurBlock->ReturnType = RetTy;
+ CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic);
+
+ // Don't allow returning an array by value.
+ if (RetTy->isArrayType()) {
+ Diag(ParamInfo.getSourceRange().getBegin(), diag::err_block_returns_array);
return;
}
- // Analyze arguments to block.
- assert(ParamInfo.getTypeObject(0).Kind == DeclaratorChunk::Function &&
- "Not a function declarator!");
- DeclaratorChunk::FunctionTypeInfo &FTI = ParamInfo.getTypeObject(0).Fun;
-
- CurBlock->hasPrototype = FTI.hasPrototype;
- CurBlock->isVariadic = true;
-
- // Check for C99 6.7.5.3p10 - foo(void) is a non-varargs function that takes
- // no arguments, not a function that takes a single void argument.
- if (FTI.hasPrototype &&
- FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&
- (!FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType().getCVRQualifiers()&&
- FTI.ArgInfo[0].Param.getAs<ParmVarDecl>()->getType()->isVoidType())) {
- // empty arg list, don't push any params.
- CurBlock->isVariadic = false;
- } else if (FTI.hasPrototype) {
- for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) {
- ParmVarDecl *Param = FTI.ArgInfo[i].Param.getAs<ParmVarDecl>();
+ // Don't allow returning a objc interface by value.
+ if (RetTy->isObjCObjectType()) {
+ Diag(ParamInfo.getSourceRange().getBegin(),
+ diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
+ return;
+ }
+
+ // Context.DependentTy is used as a placeholder for a missing block
+ // return type.
+ if (RetTy != Context.DependentTy)
+ CurBlock->ReturnType = RetTy;
+
+ // Push block parameters from the declarator if we had them.
+ if (isa<FunctionProtoType>(T)) {
+ FunctionProtoTypeLoc TL = cast<FunctionProtoTypeLoc>(Sig->getTypeLoc());
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ ParmVarDecl *Param = TL.getArg(I);
if (Param->getIdentifier() == 0 &&
!Param->isImplicit() &&
!Param->isInvalidDecl() &&
@@ -7039,13 +7024,39 @@
Diag(Param->getLocation(), diag::err_parameter_name_omitted);
CurBlock->Params.push_back(Param);
}
- CurBlock->isVariadic = FTI.isVariadic;
+
+ // Fake up parameter variables if we have a typedef, like
+ // ^ fntype { ... }
+ } else if (const FunctionProtoType *Fn = T->getAs<FunctionProtoType>()) {
+ for (FunctionProtoType::arg_type_iterator
+ I = Fn->arg_type_begin(), E = Fn->arg_type_end(); I != E; ++I) {
+ ParmVarDecl *Param =
+ BuildParmVarDeclForTypedef(CurBlock->TheDecl,
+ ParamInfo.getSourceRange().getBegin(),
+ *I);
+ CurBlock->Params.push_back(Param);
+ }
}
- CurBlock->TheDecl->setParams(CurBlock->Params.data(),
- CurBlock->Params.size());
- CurBlock->TheDecl->setIsVariadic(CurBlock->isVariadic);
+
+ // Set the parmaeters on the block decl.
+ if (!CurBlock->Params.empty())
+ CurBlock->TheDecl->setParams(CurBlock->Params.data(),
+ CurBlock->Params.size());
+
+ // Finally we can process decl attributes.
ProcessDeclAttributes(CurScope, CurBlock->TheDecl, ParamInfo);
+ if (!CurBlock->isVariadic && CurBlock->TheDecl->getAttr<SentinelAttr>()) {
+ Diag(ParamInfo.getAttributes()->getLoc(),
+ diag::warn_attribute_sentinel_not_variadic) << 1;
+ // FIXME: remove the attribute.
+ }
+
+ // Put the parameter variables in scope. We can bail out immediately
+ // if we don't have any.
+ if (CurBlock->Params.empty())
+ return;
+
bool ShouldCheckShadow =
Diags.getDiagnosticLevel(diag::warn_decl_shadow) != Diagnostic::Ignored;
@@ -7061,25 +7072,6 @@
PushOnScopeChains(*AI, CurBlock->TheScope);
}
}
-
- // Check for a valid sentinel attribute on this block.
- if (!CurBlock->isVariadic &&
- CurBlock->TheDecl->getAttr<SentinelAttr>()) {
- Diag(ParamInfo.getAttributes()->getLoc(),
- diag::warn_attribute_sentinel_not_variadic) << 1;
- // FIXME: remove the attribute.
- }
-
- // Analyze the return type.
- QualType T = GetTypeForDeclarator(ParamInfo, CurScope);
- QualType RetTy = T->getAs<FunctionType>()->getResultType();
-
- // Do not allow returning a objc interface by-value.
- if (RetTy->isObjCObjectType()) {
- Diag(ParamInfo.getSourceRange().getBegin(),
- diag::err_object_cannot_be_passed_returned_by_value) << 0 << RetTy;
- } else if (!RetTy->isDependentType())
- CurBlock->ReturnType = RetTy;
}
/// ActOnBlockError - If there is an error parsing a block, this callback
More information about the cfe-commits
mailing list