[cfe-commits] r122162 - in /cfe/trunk: include/clang/AST/ASTContext.h lib/AST/ASTContext.cpp lib/Sema/SemaDecl.cpp lib/Sema/SemaExprCXX.cpp lib/Sema/SemaType.cpp
John McCall
rjmccall at apple.com
Sat Dec 18 18:44:49 PST 2010
Author: rjmccall
Date: Sat Dec 18 20:44:49 2010
New Revision: 122162
URL: http://llvm.org/viewvc/llvm-project?rev=122162&view=rev
Log:
Motions towards simplifying how we deal with attribute-qualified function types.
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/Sema/SemaDecl.cpp
cfe/trunk/lib/Sema/SemaExprCXX.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=122162&r1=122161&r2=122162&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Sat Dec 18 20:44:49 2010
@@ -479,21 +479,15 @@
/// equivalent to calling T.withConst().
QualType getConstType(QualType T) { return T.withConst(); }
+ /// adjustFunctionType - Change the ExtInfo on a function type.
+ const FunctionType *adjustFunctionType(const FunctionType *Fn,
+ FunctionType::ExtInfo EInfo);
+
/// getNoReturnType - Add or remove the noreturn attribute to the given type
/// which must be a FunctionType or a pointer to an allowable type or a
/// BlockPointer.
QualType getNoReturnType(QualType T, bool AddNoReturn = true);
- /// getCallConvType - Adds the specified calling convention attribute to
- /// the given type, which must be a FunctionType or a pointer to an
- /// allowable type.
- QualType getCallConvType(QualType T, CallingConv CallConv);
-
- /// getRegParmType - Sets the specified regparm attribute to
- /// the given type, which must be a FunctionType or a pointer to an
- /// allowable type.
- QualType getRegParmType(QualType T, unsigned RegParm);
-
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=122162&r1=122161&r2=122162&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Sat Dec 18 20:44:49 2010
@@ -1140,8 +1140,27 @@
return getExtQualType(TypeNode, Quals);
}
+const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T,
+ FunctionType::ExtInfo Info) {
+ if (T->getExtInfo() == Info)
+ return T;
+
+ QualType Result;
+ if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(T)) {
+ Result = getFunctionNoProtoType(FNPT->getResultType(), Info);
+ } else {
+ const FunctionProtoType *FPT = cast<FunctionProtoType>(T);
+ FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+ EPI.ExtInfo = Info;
+ Result = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(),
+ FPT->getNumArgs(), EPI);
+ }
+
+ return cast<FunctionType>(Result.getTypePtr());
+}
+
static QualType getExtFunctionType(ASTContext& Context, QualType T,
- const FunctionType::ExtInfo &Info) {
+ FunctionType::ExtInfo Info) {
QualType ResultType;
if (const PointerType *Pointer = T->getAs<PointerType>()) {
QualType Pointee = Pointer->getPointeeType();
@@ -1175,20 +1194,7 @@
ResultType = Context.getMemberPointerType(ResultType,
MemberPointer->getClass());
} else if (const FunctionType *F = T->getAs<FunctionType>()) {
- if (F->getExtInfo() == Info)
- return T;
-
- if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(F)) {
- ResultType = Context.getFunctionNoProtoType(FNPT->getResultType(),
- Info);
- } else {
- const FunctionProtoType *FPT = cast<FunctionProtoType>(F);
- FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
- EPI.ExtInfo = Info;
- ResultType = Context.getFunctionType(FPT->getResultType(),
- FPT->arg_type_begin(),
- FPT->getNumArgs(), EPI);
- }
+ ResultType = QualType(Context.adjustFunctionType(F, Info), 0);
} else
return T;
@@ -1200,16 +1206,6 @@
return getExtFunctionType(*this, T, Info.withNoReturn(AddNoReturn));
}
-QualType ASTContext::getCallConvType(QualType T, CallingConv CallConv) {
- FunctionType::ExtInfo Info = getFunctionExtInfo(T);
- return getExtFunctionType(*this, T, Info.withCallingConv(CallConv));
-}
-
-QualType ASTContext::getRegParmType(QualType T, unsigned RegParm) {
- FunctionType::ExtInfo Info = getFunctionExtInfo(T);
- return getExtFunctionType(*this, T, Info.withRegParm(RegParm));
-}
-
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType ASTContext::getComplexType(QualType T) {
Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=122162&r1=122161&r2=122162&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Dec 18 20:44:49 2010
@@ -1140,15 +1140,15 @@
//
// Note also that we DO NOT return at this point, because we still have
// other tests to run.
- const FunctionType *OldType = OldQType->getAs<FunctionType>();
+ const FunctionType *OldType = cast<FunctionType>(OldQType);
const FunctionType *NewType = New->getType()->getAs<FunctionType>();
- const FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
- const FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
+ FunctionType::ExtInfo OldTypeInfo = OldType->getExtInfo();
+ FunctionType::ExtInfo NewTypeInfo = NewType->getExtInfo();
+ bool RequiresAdjustment = false;
if (OldTypeInfo.getCC() != CC_Default &&
NewTypeInfo.getCC() == CC_Default) {
- NewQType = Context.getCallConvType(NewQType, OldTypeInfo.getCC());
- New->setType(NewQType);
- NewQType = Context.getCanonicalType(NewQType);
+ NewTypeInfo = NewTypeInfo.withCallingConv(OldTypeInfo.getCC());
+ RequiresAdjustment = true;
} else if (!Context.isSameCallConv(OldTypeInfo.getCC(),
NewTypeInfo.getCC())) {
// Calling conventions really aren't compatible, so complain.
@@ -1162,25 +1162,29 @@
}
// FIXME: diagnose the other way around?
- if (OldType->getNoReturnAttr() && !NewType->getNoReturnAttr()) {
- NewQType = Context.getNoReturnType(NewQType);
- New->setType(NewQType);
- assert(NewQType.isCanonical());
+ if (OldTypeInfo.getNoReturn() && !NewTypeInfo.getNoReturn()) {
+ NewTypeInfo = NewTypeInfo.withNoReturn(true);
+ RequiresAdjustment = true;
}
// Merge regparm attribute.
- if (OldType->getRegParmType() != NewType->getRegParmType()) {
- if (NewType->getRegParmType()) {
+ if (OldTypeInfo.getRegParm() != NewTypeInfo.getRegParm()) {
+ if (NewTypeInfo.getRegParm()) {
Diag(New->getLocation(), diag::err_regparm_mismatch)
<< NewType->getRegParmType()
<< OldType->getRegParmType();
Diag(Old->getLocation(), diag::note_previous_declaration);
return true;
}
-
- NewQType = Context.getRegParmType(NewQType, OldType->getRegParmType());
- New->setType(NewQType);
- assert(NewQType.isCanonical());
+
+ NewTypeInfo = NewTypeInfo.withRegParm(OldTypeInfo.getRegParm());
+ RequiresAdjustment = true;
+ }
+
+ if (RequiresAdjustment) {
+ NewType = Context.adjustFunctionType(NewType, NewTypeInfo);
+ New->setType(QualType(NewType, 0));
+ NewQType = Context.getCanonicalType(New->getType());
}
if (getLangOptions().CPlusPlus) {
@@ -1188,10 +1192,8 @@
// Certain function declarations cannot be overloaded:
// -- Function declarations that differ only in the return type
// cannot be overloaded.
- QualType OldReturnType
- = cast<FunctionType>(OldQType.getTypePtr())->getResultType();
- QualType NewReturnType
- = cast<FunctionType>(NewQType.getTypePtr())->getResultType();
+ QualType OldReturnType = OldType->getResultType();
+ QualType NewReturnType = cast<FunctionType>(NewQType)->getResultType();
QualType ResQT;
if (OldReturnType != NewReturnType) {
if (NewReturnType->isObjCObjectPointerType()
@@ -1261,9 +1263,19 @@
// (C++98 8.3.5p3):
// All declarations for a function shall agree exactly in both the
// return type and the parameter-type-list.
- // attributes should be ignored when comparing.
- if (Context.getNoReturnType(OldQType, false) ==
- Context.getNoReturnType(NewQType, false))
+ // We also want to respect all the extended bits except noreturn.
+
+ // noreturn should now match unless the old type info didn't have it.
+ QualType OldQTypeForComparison = OldQType;
+ if (!OldTypeInfo.getNoReturn() && NewTypeInfo.getNoReturn()) {
+ assert(OldQType == QualType(OldType, 0));
+ const FunctionType *OldTypeForComparison
+ = Context.adjustFunctionType(OldType, OldTypeInfo.withNoReturn(true));
+ OldQTypeForComparison = QualType(OldTypeForComparison, 0);
+ assert(OldQTypeForComparison.isCanonical());
+ }
+
+ if (OldQTypeForComparison == NewQType)
return MergeCompatibleFunctionDecls(New, Old);
// Fall through for conflicting redeclarations and redefinitions.
Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=122162&r1=122161&r2=122162&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Sat Dec 18 20:44:49 2010
@@ -1895,8 +1895,7 @@
if (CheckExceptionSpecCompatibility(From, ToType))
return true;
- ImpCastExprToType(From, Context.getNoReturnType(From->getType(), false),
- CK_NoOp);
+ ImpCastExprToType(From, ToType, CK_NoOp);
break;
case ICK_Integral_Promotion:
Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=122162&r1=122161&r2=122162&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Sat Dec 18 20:44:49 2010
@@ -1891,9 +1891,142 @@
Type = S.Context.getObjCGCQualType(Type, GCAttr);
}
+namespace {
+ /// A helper class to unwrap a type down to a function for the
+ /// purposes of applying attributes there.
+ ///
+ /// Use:
+ /// FunctionTypeUnwrapper unwrapped(SemaRef, T);
+ /// if (unwrapped.isFunctionType()) {
+ /// const FunctionType *fn = unwrapped.get();
+ /// // change fn somehow
+ /// T = unwrapped.wrap(fn);
+ /// }
+ struct FunctionTypeUnwrapper {
+ enum WrapKind {
+ Desugar,
+ Parens,
+ Pointer,
+ BlockPointer,
+ Reference,
+ MemberPointer
+ };
+
+ QualType Original;
+ const FunctionType *Fn;
+ llvm::SmallVector<unsigned char /*WrapKind*/, 8> Stack;
+
+ FunctionTypeUnwrapper(Sema &S, QualType T) : Original(T) {
+ while (true) {
+ const Type *Ty = T.getTypePtr();
+ if (isa<FunctionType>(Ty)) {
+ Fn = cast<FunctionType>(Ty);
+ return;
+ } else if (isa<ParenType>(Ty)) {
+ T = cast<ParenType>(Ty)->getInnerType();
+ Stack.push_back(Parens);
+ } else if (isa<PointerType>(Ty)) {
+ T = cast<PointerType>(Ty)->getPointeeType();
+ Stack.push_back(Pointer);
+ } else if (isa<BlockPointerType>(Ty)) {
+ T = cast<BlockPointerType>(Ty)->getPointeeType();
+ Stack.push_back(BlockPointer);
+ } else if (isa<MemberPointerType>(Ty)) {
+ T = cast<MemberPointerType>(Ty)->getPointeeType();
+ Stack.push_back(MemberPointer);
+ } else if (isa<ReferenceType>(Ty)) {
+ T = cast<ReferenceType>(Ty)->getPointeeType();
+ Stack.push_back(Reference);
+ } else {
+ const Type *DTy = Ty->getUnqualifiedDesugaredType();
+ if (Ty == DTy) {
+ Fn = 0;
+ return;
+ }
+
+ T = QualType(DTy, 0);
+ Stack.push_back(Desugar);
+ }
+ }
+ }
+
+ bool isFunctionType() const { return (Fn != 0); }
+ const FunctionType *get() const { return Fn; }
+
+ QualType wrap(Sema &S, const FunctionType *New) {
+ // If T wasn't modified from the unwrapped type, do nothing.
+ if (New == get()) return Original;
+
+ Fn = New;
+ return wrap(S.Context, Original, 0);
+ }
+
+ private:
+ QualType wrap(ASTContext &C, QualType Old, unsigned I) {
+ if (I == Stack.size())
+ return C.getQualifiedType(Fn, Old.getQualifiers());
+
+ // Build up the inner type, applying the qualifiers from the old
+ // type to the new type.
+ SplitQualType SplitOld = Old.split();
+
+ // As a special case, tail-recurse if there are no qualifiers.
+ if (SplitOld.second.empty())
+ return wrap(C, SplitOld.first, I);
+ return C.getQualifiedType(wrap(C, SplitOld.first, I), SplitOld.second);
+ }
+
+ QualType wrap(ASTContext &C, const Type *Old, unsigned I) {
+ if (I == Stack.size()) return QualType(Fn, 0);
+
+ switch (static_cast<WrapKind>(Stack[I++])) {
+ case Desugar:
+ // This is the point at which we potentially lose source
+ // information.
+ return wrap(C, Old->getUnqualifiedDesugaredType(), I);
+
+ case Parens: {
+ QualType New = wrap(C, cast<ParenType>(Old)->getInnerType(), I);
+ return C.getParenType(New);
+ }
+
+ case Pointer: {
+ QualType New = wrap(C, cast<PointerType>(Old)->getPointeeType(), I);
+ return C.getPointerType(New);
+ }
+
+ case BlockPointer: {
+ QualType New = wrap(C, cast<BlockPointerType>(Old)->getPointeeType(),I);
+ return C.getBlockPointerType(New);
+ }
+
+ case MemberPointer: {
+ const MemberPointerType *OldMPT = cast<MemberPointerType>(Old);
+ QualType New = wrap(C, OldMPT->getPointeeType(), I);
+ return C.getMemberPointerType(New, OldMPT->getClass());
+ }
+
+ case Reference: {
+ const ReferenceType *OldRef = cast<ReferenceType>(Old);
+ QualType New = wrap(C, OldRef->getPointeeType(), I);
+ if (isa<LValueReferenceType>(OldRef))
+ return C.getLValueReferenceType(New, OldRef->isSpelledAsLValue());
+ else
+ return C.getRValueReferenceType(New);
+ }
+ }
+
+ llvm_unreachable("unknown wrapping kind");
+ return QualType();
+ }
+ };
+}
+
/// Process an individual function attribute. Returns true if the
/// attribute does not make sense to apply to this type.
-bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
+static bool ProcessFnAttr(Sema &S, QualType &Type, const AttributeList &Attr) {
+ FunctionTypeUnwrapper Unwrapped(S, Type);
+
if (Attr.getKind() == AttributeList::AT_noreturn) {
// Complain immediately if the arg count is wrong.
if (Attr.getNumArgs() != 0) {
@@ -1902,15 +2035,13 @@
return false;
}
- // Delay if this is not a function or pointer to block.
- if (!Type->isFunctionPointerType()
- && !Type->isBlockPointerType()
- && !Type->isFunctionType()
- && !Type->isMemberFunctionPointerType())
+ // Delay if this is not a function type.
+ if (!Unwrapped.isFunctionType())
return true;
-
+
// Otherwise we can process right away.
- Type = S.Context.getNoReturnType(Type);
+ FunctionType::ExtInfo EI = Unwrapped.get()->getExtInfo().withNoReturn(true);
+ Type = Unwrapped.wrap(S, S.Context.adjustFunctionType(Unwrapped.get(), EI));
return false;
}
@@ -1920,11 +2051,8 @@
return false;
}
- // Delay if this is not a function or pointer to block.
- if (!Type->isFunctionPointerType()
- && !Type->isBlockPointerType()
- && !Type->isFunctionType()
- && !Type->isMemberFunctionPointerType())
+ // Delay if this is not a function type.
+ if (!Unwrapped.isFunctionType())
return true;
// Otherwise we can process right away.
@@ -1950,7 +2078,9 @@
return false;
}
- Type = S.Context.getRegParmType(Type, NumParams.getZExtValue());
+ FunctionType::ExtInfo EI =
+ Unwrapped.get()->getExtInfo().withRegParm(NumParams.getZExtValue());
+ Type = Unwrapped.wrap(S, S.Context.adjustFunctionType(Unwrapped.get(), EI));
return false;
}
@@ -1961,19 +2091,8 @@
return false;
}
- QualType T = Type;
- if (const PointerType *PT = Type->getAs<PointerType>())
- T = PT->getPointeeType();
- else if (const BlockPointerType *BPT = Type->getAs<BlockPointerType>())
- T = BPT->getPointeeType();
- else if (const MemberPointerType *MPT = Type->getAs<MemberPointerType>())
- T = MPT->getPointeeType();
- else if (const ReferenceType *RT = Type->getAs<ReferenceType>())
- T = RT->getPointeeType();
- const FunctionType *Fn = T->getAs<FunctionType>();
-
// Delay if the type didn't work out to a function.
- if (!Fn) return true;
+ if (!Unwrapped.isFunctionType()) return true;
// TODO: diagnose uses of these conventions on the wrong target.
CallingConv CC;
@@ -1986,6 +2105,7 @@
default: llvm_unreachable("unexpected attribute kind"); return false;
}
+ const FunctionType *Fn = Unwrapped.get();
CallingConv CCOld = Fn->getCallConv();
if (S.Context.getCanonicalCallConv(CC) ==
S.Context.getCanonicalCallConv(CCOld)) {
@@ -2020,7 +2140,8 @@
}
}
- Type = S.Context.getCallConvType(Type, CC);
+ FunctionType::ExtInfo EI = Unwrapped.get()->getExtInfo().withCallingConv(CC);
+ Type = Unwrapped.wrap(S, S.Context.adjustFunctionType(Unwrapped.get(), EI));
return false;
}
More information about the cfe-commits
mailing list