[cfe-commits] [patch] Qualifiers refactor
Douglas Gregor
dgregor at apple.com
Thu Sep 24 08:58:26 PDT 2009
On Sep 23, 2009, at 2:04 AM, John McCall wrote:
> The attached patch refactors how qualifiers are represented in clang.
>
> Currently, QualType uses the bottom three bits of a type pointer to
> represent the const, volatile, and restrict qualifiers. Extended
> qualifiers are represented using an ExtQualType object, which is an
> ordinary node in the type hierarchy --- except that it isn't. Most
> common operations on types have to explicitly check for these
> special qualifier nodes and handle them differently.
... except that most common operations end up forgetting that
ExtQualType exists. One of the big benefits of this change is that all
of the qualifiers are kept together, so it's easier to reason about
them as a whole. Plus, ExtQualType didn't fit well into the type
system; this does.
> This patch changes QualType to store only two qualifiers directly on
> the pointer; the third bit is repurposed to signal whether the
> pointer is a Type or an ExtQuals object (which holds, but is not, a
> Type). This makes it very cheap to decide whether a type carries
> any qualifiers, as well as to compute the unqualified version of a
> type.
>
> Because there are only two remaining bits, it's necessary to store
> 'volatile' on the ExtQuals object, 'const' being ubiquitous and
> 'restrict' being common in certain system headers.
Right. A quick check of my system headers found 53507 uses of 'const',
1691 uses of 'restrict', and 609 uses of 'volatile'.
> This could be avoided by using 16-byte alignment on Types, which
> would be extremely straightforward to do under the patch (modulo any
> possible required changes to the allocator, which I haven't
> investigated).
>
> This patch also audits many of the uses of qualifiers in clang,
> adjusting them to handle arbitrary qualifiers (or be augmentable for
> future qualifiers) when that was reasonably straightforward.
I think this patch is great. The one downside I see is that it causes
Clang -fparse-only on Cocoa.h (from a token cache) to run about 4%
slower (#'s at the end). However, I'm willing to pay that cost to get
the API improvements this patch brings.
A few minor comments:
In lib/CodeGen/CGValue.h,
@@ -187,21 +173,18 @@ public:
bool isPropertyRef() const { return LVType == PropertyRef; }
bool isKVCRef() const { return LVType == KVCRef; }
- bool isVolatileQualified() const { return Volatile; }
- bool isRestrictQualified() const { return Restrict; }
- unsigned getQualifiers() const {
- return (Volatile ? QualType::Volatile : 0) |
- (Restrict ? QualType::Restrict : 0);
- }
+ bool isVolatileQualified() const { return Quals.hasVolatile(); }
+ bool isRestrictQualified() const { return Quals.hasRestrict(); }
+ unsigned getVRQualifiers() const { return Quals.getCVRQualifiers(); }
getVRQualifiers() should mask off the Const bit.
@@ -1675,8 +1674,10 @@ QualType Sema::CXXCheckConditionalOperan
// The type 'Q Pointee (MoreDerived::*)' is the common type.
// We don't use ImpCastExprToType here because this could
still fail
// for ambiguous or inaccessible conversions.
- QualType Common = Context.getMemberPointerType(
- LPointee.getQualifiedType(Q), MoreDerived.getTypePtr());
+ LPointee
+ = Context.getQualifiedType(LPointee,
Qualifiers::fromCVRMask(CVR));
+ QualType Common
+ = Context.getMemberPointerType(LPointee,
MoreDerived.getTypePtr());
if (PerformImplicitConversion(LHS, Common, "converting"))
return QualType();
if (PerformImplicitConversion(RHS, Common, "converting"))
I think this will lose non-CVR qualifiers on the pointer type (the
previous code probably had the same issue). Of course, it doesn't look
like we're checking that the pointers have the same address spaces,
either.
@@ -1778,16 +1779,21 @@ QualType Sema::FindCompositePointerType(
I = QualifierUnion.begin(),
E = QualifierUnion.end();
I != E; (void)++I, ++MOC) {
+ Qualifiers Quals = Qualifiers::fromCVRMask(*I);
if (MOC->first && MOC->second) {
// Rebuild member pointer type
- Composite1 = Context.getMemberPointerType
(Composite1.getQualifiedType(*I),
- MOC->first);
- Composite2 = Context.getMemberPointerType
(Composite2.getQualifiedType(*I),
- MOC->second);
+ Composite1 = Context.getMemberPointerType(
+ Context.getQualifiedType
(Composite1, Quals),
+ MOC->first);
+ Composite2 = Context.getMemberPointerType(
+ Context.getQualifiedType
(Composite2, Quals),
+ MOC->second);
} else {
// Rebuild pointer type
- Composite1 = Context.getPointerType(Composite1.getQualifiedType
(*I));
- Composite2 = Context.getPointerType(Composite2.getQualifiedType
(*I));
+ Composite1
+ = Context.getPointerType(Context.getQualifiedType(Composite1,
Quals));
+ Composite2
+ = Context.getPointerType(Context.getQualifiedType(Composite2,
Quals));
}
}
Same concern here; we're probably losing non-CVR qualifiers.
Looking at the template argument deduction code, I thought of an
amusing case that we don't need to support (but might be a little
harder now):
template<typename T>
struct address_space_of {
static const unsigned value = 0;
};
template<typename T, unsigned N>
struct address_space_of<T * __attribute__((address_space(N))> {
static const unsigned value = N;
};
Don't worry about this case now, of course.
In lib/Sema/SemaOverload.cpp, BuiltinCandidateTypeSet should probably
have a blanket FIXME to cope with extended qualification. I don't
quite know what the semantics should be, but we'll have to think about
it at some point.
@@ -340,12 +340,14 @@ QualType Sema::ConvertDeclSpecToType(con
if (Result->isFunctionType() && TypeQuals) {
// Get some location to point at, either the C or V location.
SourceLocation Loc;
- if (TypeQuals & QualType::Const)
+ if (TypeQuals & DeclSpec::TQ_const)
Loc = DS.getConstSpecLoc();
@@ -2415,18 +2385,21 @@ QualType ASTContext::getArrayDecayedType
QualType PtrTy = getPointerType(PrettyArrayType->getElementType());
+ llvm::errs() << "array type decaying from " << Ty.getAsString() <<
" to " << PtrTy.getAsString() << "\n";
+ llvm::errs() << "element type is " << PrettyArrayType-
>getElementType().getAsString() << "\n";
+
You might want to remove those debugging statements ;)
Very nice!
- Doug
Before:
clang-cc -token-cache /tmp/tokencache INPUTS/Cocoa_h.m
name avg min med max SD total
user 0.2142 0.2140 0.2142 0.2144 0.0002 1.0710
sys 0.0319 0.0320 0.0326 0.0314 0.0005 0.1597
wall 0.2504 0.2502 0.2512 0.2501 0.0005 1.2520
After:
name avg min med max SD total
user 0.2234 0.2234 0.2234 0.2236 0.0001 1.1172
sys 0.0320 0.0333 0.0309 0.0312 0.0009 0.1598
wall 0.2596 0.2609 0.2584 0.2590 0.0009 1.2982
More information about the cfe-commits
mailing list