mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1201309 - Make MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS work with MOZ_NON_MEMMOVABLE. r=ehsan f=mystor
This patch migrates moz_non_memmovable into the CustomTypeAnnotation framework; bonus side-effects are more helpful error messages and less code duplication.
This commit is contained in:
parent
6b322647d6
commit
df9223fa57
@ -280,6 +280,8 @@ static CustomTypeAnnotation HeapClass =
|
||||
CustomTypeAnnotation("moz_heap_class", "heap");
|
||||
static CustomTypeAnnotation MustUse =
|
||||
CustomTypeAnnotation("moz_must_use", "must-use");
|
||||
static CustomTypeAnnotation NonMemMovable =
|
||||
CustomTypeAnnotation("moz_non_memmovable", "non-memmove()able");
|
||||
|
||||
class MozChecker : public ASTConsumer, public RecursiveASTVisitor<MozChecker> {
|
||||
DiagnosticsEngine &Diag;
|
||||
@ -474,92 +476,6 @@ bool isClassRefCounted(QualType T) {
|
||||
return clazz ? isClassRefCounted(clazz) : false;
|
||||
}
|
||||
|
||||
/// A cached data of whether classes are memmovable, and if not, what
|
||||
/// declaration
|
||||
/// makes them non-movable
|
||||
typedef DenseMap<const CXXRecordDecl *, const CXXRecordDecl *>
|
||||
InferredMovability;
|
||||
InferredMovability inferredMovability;
|
||||
|
||||
bool isClassNonMemMovable(QualType T);
|
||||
const CXXRecordDecl *isClassNonMemMovableWorker(QualType T);
|
||||
|
||||
const CXXRecordDecl *isClassNonMemMovableWorker(const CXXRecordDecl *D) {
|
||||
// If we have a definition, then we want to standardize our reference to point
|
||||
// to the definition node. If we don't have a definition, that means that
|
||||
// either
|
||||
// we only have a forward declaration of the type in our file, or we are being
|
||||
// passed a template argument which is not used, and thus never instantiated
|
||||
// by
|
||||
// clang.
|
||||
// As the argument isn't used, we can't memmove it (as we don't know it's
|
||||
// size),
|
||||
// which means not reporting an error is OK.
|
||||
if (!D->hasDefinition()) {
|
||||
return 0;
|
||||
}
|
||||
D = D->getDefinition();
|
||||
|
||||
// Are we explicitly marked as non-memmovable class?
|
||||
if (MozChecker::hasCustomAnnotation(D, "moz_non_memmovable")) {
|
||||
return D;
|
||||
}
|
||||
|
||||
// Look through all base cases to figure out if the parent is a non-memmovable
|
||||
// class.
|
||||
for (CXXRecordDecl::base_class_const_iterator base = D->bases_begin();
|
||||
base != D->bases_end(); ++base) {
|
||||
const CXXRecordDecl *result = isClassNonMemMovableWorker(base->getType());
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Look through all members to figure out if a member is a non-memmovable
|
||||
// class.
|
||||
for (RecordDecl::field_iterator field = D->field_begin(), e = D->field_end();
|
||||
field != e; ++field) {
|
||||
const CXXRecordDecl *result = isClassNonMemMovableWorker(field->getType());
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const CXXRecordDecl *isClassNonMemMovableWorker(QualType T) {
|
||||
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
|
||||
T = arrTy->getElementType();
|
||||
const CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
|
||||
return clazz ? isClassNonMemMovableWorker(clazz) : 0;
|
||||
}
|
||||
|
||||
bool isClassNonMemMovable(const CXXRecordDecl *D) {
|
||||
InferredMovability::iterator it = inferredMovability.find(D);
|
||||
if (it != inferredMovability.end())
|
||||
return !!it->second;
|
||||
const CXXRecordDecl *result = isClassNonMemMovableWorker(D);
|
||||
inferredMovability.insert(std::make_pair(D, result));
|
||||
return !!result;
|
||||
}
|
||||
|
||||
bool isClassNonMemMovable(QualType T) {
|
||||
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
|
||||
T = arrTy->getElementType();
|
||||
const CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
|
||||
return clazz ? isClassNonMemMovable(clazz) : false;
|
||||
}
|
||||
|
||||
const CXXRecordDecl *findWhyClassIsNonMemMovable(QualType T) {
|
||||
while (const ArrayType *arrTy = T->getAsArrayTypeUnsafe())
|
||||
T = arrTy->getElementType();
|
||||
CXXRecordDecl *clazz = T->getAsCXXRecordDecl();
|
||||
InferredMovability::iterator it = inferredMovability.find(clazz);
|
||||
assert(it != inferredMovability.end());
|
||||
return it->second;
|
||||
}
|
||||
|
||||
template <class T> bool IsInSystemHeader(const ASTContext &AC, const T &D) {
|
||||
auto &SourceManager = AC.getSourceManager();
|
||||
auto ExpansionLoc = SourceManager.getExpansionLoc(D.getLocStart());
|
||||
@ -719,7 +635,9 @@ AST_MATCHER(CXXRecordDecl, hasNeedsNoVTableTypeAttr) {
|
||||
}
|
||||
|
||||
/// This matcher will select classes which are non-memmovable
|
||||
AST_MATCHER(QualType, isNonMemMovable) { return isClassNonMemMovable(Node); }
|
||||
AST_MATCHER(QualType, isNonMemMovable) {
|
||||
return NonMemMovable.hasEffectiveAnnotation(Node);
|
||||
}
|
||||
|
||||
/// This matcher will select classes which require a memmovable template arg
|
||||
AST_MATCHER(CXXRecordDecl, needsMemMovable) {
|
||||
@ -803,6 +721,7 @@ void CustomTypeAnnotation::dumpAnnotationReason(DiagnosticsEngine &Diag,
|
||||
break;
|
||||
}
|
||||
default:
|
||||
// FIXME (bug 1203263): note the original annotation.
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1323,11 +1242,6 @@ void DiagnosticsMatcher::NonMemMovableChecker::run(
|
||||
"Cannot instantiate %0 with non-memmovable template argument %1");
|
||||
unsigned note1ID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Note, "instantiation of %0 requested here");
|
||||
unsigned note2ID = Diag.getDiagnosticIDs()->getCustomDiagID(
|
||||
DiagnosticIDs::Note, "%0 is non-memmovable because of the "
|
||||
"MOZ_NON_MEMMOVABLE annotation on %1");
|
||||
unsigned note3ID =
|
||||
Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Note, "%0");
|
||||
|
||||
// Get the specialization
|
||||
const ClassTemplateSpecializationDecl *specialization =
|
||||
@ -1341,8 +1255,7 @@ void DiagnosticsMatcher::NonMemMovableChecker::run(
|
||||
specialization->getTemplateInstantiationArgs();
|
||||
for (unsigned i = 0; i < args.size(); ++i) {
|
||||
QualType argType = args[i].getAsType();
|
||||
if (isClassNonMemMovable(args[i].getAsType())) {
|
||||
const CXXRecordDecl *reason = findWhyClassIsNonMemMovable(argType);
|
||||
if (NonMemMovable.hasEffectiveAnnotation(args[i].getAsType())) {
|
||||
Diag.Report(specialization->getLocation(), errorID) << specialization
|
||||
<< argType;
|
||||
// XXX It would be really nice if we could get the instantiation stack
|
||||
@ -1355,7 +1268,7 @@ void DiagnosticsMatcher::NonMemMovableChecker::run(
|
||||
// cases won't
|
||||
// be useful)
|
||||
Diag.Report(requestLoc, note1ID) << specialization;
|
||||
Diag.Report(reason->getLocation(), note2ID) << argType << reason;
|
||||
NonMemMovable.dumpAnnotationReason(Diag, argType, requestLoc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,37 @@
|
||||
#define MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS \
|
||||
__attribute__((annotate("moz_inherit_type_annotations_from_template_args")))
|
||||
#define MOZ_STACK_CLASS __attribute__((annotate("moz_stack_class")))
|
||||
#define MOZ_NON_MEMMOVABLE __attribute__((annotate("moz_non_memmovable")))
|
||||
#define MOZ_NEEDS_MEMMOVABLE_TYPE __attribute__((annotate("moz_needs_memmovable_type")))
|
||||
|
||||
class Normal {};
|
||||
class MOZ_STACK_CLASS Stack {};
|
||||
class IndirectStack : Stack {}; // expected-note {{'IndirectStack' is a stack type because it inherits from a stack type 'Stack'}}
|
||||
class ContainsStack { Stack m; }; // expected-note {{'ContainsStack' is a stack type because member 'm' is a stack type 'Stack'}}
|
||||
class MOZ_NON_MEMMOVABLE Pointery {};
|
||||
class IndirectPointery : Pointery {}; // expected-note {{'IndirectPointery' is a non-memmove()able type because it inherits from a non-memmove()able type 'Pointery'}}
|
||||
class ContainsPointery { Pointery m; }; // expected-note {{'ContainsPointery' is a non-memmove()able type because member 'm' is a non-memmove()able type 'Pointery'}}
|
||||
|
||||
template<class T>
|
||||
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Template {}; // expected-note 2 {{'Template<Stack>' is a stack type because it has a template argument stack type 'Stack'}} expected-note {{'Template<IndirectStack>' is a stack type because it has a template argument stack type 'IndirectStack'}}
|
||||
class MOZ_INHERIT_TYPE_ANNOTATIONS_FROM_TEMPLATE_ARGS Template {}; // expected-note-re 5 {{'Template<{{.*}}>' is a stack type because it has a template argument stack type '{{.*}}'}} expected-note-re 5 {{'Template<{{.*}}>' is a non-memmove()able type because it has a template argument non-memmove()able type '{{.*}}'}}
|
||||
class IndirectTemplate : Template<Stack> {}; // expected-note {{'IndirectTemplate' is a stack type because it inherits from a stack type 'Template<Stack>'}}
|
||||
class ContainsTemplate { Template<Stack> m; }; // expected-note {{'ContainsTemplate' is a stack type because member 'm' is a stack type 'Template<Stack>'}}
|
||||
|
||||
static Template<Stack> a; // expected-error {{variable of type 'Template<Stack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
static Template<IndirectStack> b; // expected-error {{variable of type 'Template<IndirectStack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
static Template<Normal> c;
|
||||
static Template<ContainsStack> c; // expected-error {{variable of type 'Template<ContainsStack>' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
static IndirectTemplate d; // expected-error {{variable of type 'IndirectTemplate' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
static ContainsTemplate e; // expected-error {{variable of type 'ContainsTemplate' only valid on the stack}} expected-note {{value incorrectly allocated in a global variable}}
|
||||
static Template<Normal> f;
|
||||
|
||||
template<class T>
|
||||
class MOZ_NEEDS_MEMMOVABLE_TYPE Mover { char mForceInstantiation[sizeof(T)]; }; // expected-error-re 5 {{Cannot instantiate 'Mover<{{.*}}>' with non-memmovable template argument '{{.*}}'}}
|
||||
class IndirectTemplatePointery : Template<Pointery> {}; // expected-note {{'IndirectTemplatePointery' is a non-memmove()able type because it inherits from a non-memmove()able type 'Template<Pointery>'}}
|
||||
class ContainsTemplatePointery { Template<Pointery> m; }; // expected-note {{'ContainsTemplatePointery' is a non-memmove()able type because member 'm' is a non-memmove()able type 'Template<Pointery>'}}
|
||||
|
||||
static Mover<Template<Pointery>> n; // expected-note {{instantiation of 'Mover<Template<Pointery> >' requested here}}
|
||||
static Mover<Template<IndirectPointery>> o; // expected-note {{instantiation of 'Mover<Template<IndirectPointery> >' requested here}}
|
||||
static Mover<Template<ContainsPointery>> p; // expected-note {{instantiation of 'Mover<Template<ContainsPointery> >' requested here}}
|
||||
static Mover<IndirectTemplatePointery> q; // expected-note {{instantiation of 'Mover<IndirectTemplatePointery>' requested here}}
|
||||
static Mover<ContainsTemplatePointery> r; // expected-note {{instantiation of 'Mover<ContainsTemplatePointery>' requested here}}
|
||||
static Mover<Template<Normal>> s;
|
||||
|
@ -5,16 +5,16 @@
|
||||
These are a bunch of structs with variable levels of memmovability.
|
||||
They will be used as template parameters to the various NeedyTemplates
|
||||
*/
|
||||
struct MOZ_NON_MEMMOVABLE NonMovable {}; // expected-note-re + {{'{{.*}}' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'NonMovable'}}
|
||||
struct MOZ_NON_MEMMOVABLE NonMovable {};
|
||||
struct Movable {};
|
||||
|
||||
// Subclasses
|
||||
struct S_NonMovable : NonMovable {};
|
||||
struct S_NonMovable : NonMovable {}; // expected-note 48 {{'S_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'NonMovable'}}
|
||||
struct S_Movable : Movable {};
|
||||
|
||||
// Members
|
||||
struct W_NonMovable {
|
||||
NonMovable m;
|
||||
NonMovable m; // expected-note 32 {{'W_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'NonMovable'}}
|
||||
};
|
||||
struct W_Movable {
|
||||
Movable m;
|
||||
@ -22,23 +22,23 @@ struct W_Movable {
|
||||
|
||||
// Wrapped Subclasses
|
||||
struct WS_NonMovable {
|
||||
S_NonMovable m;
|
||||
S_NonMovable m; // expected-note 32 {{'WS_NonMovable' is a non-memmove()able type because member 'm' is a non-memmove()able type 'S_NonMovable'}}
|
||||
};
|
||||
struct WS_Movable {
|
||||
S_Movable m;
|
||||
};
|
||||
|
||||
// Combinations of the above
|
||||
struct SW_NonMovable : W_NonMovable {};
|
||||
struct SW_NonMovable : W_NonMovable {}; // expected-note 16 {{'SW_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'W_NonMovable'}}
|
||||
struct SW_Movable : W_Movable {};
|
||||
|
||||
struct SWS_NonMovable : WS_NonMovable {};
|
||||
struct SWS_NonMovable : WS_NonMovable {}; // expected-note 16 {{'SWS_NonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'WS_NonMovable'}}
|
||||
struct SWS_Movable : WS_Movable {};
|
||||
|
||||
// Basic templated wrapper
|
||||
template <class T>
|
||||
struct Template_Inline {
|
||||
T m;
|
||||
T m; // expected-note-re 56 {{'Template_Inline<{{.*}}>' is a non-memmove()able type because member 'm' is a non-memmove()able type '{{.*}}'}}
|
||||
};
|
||||
|
||||
template <class T>
|
||||
@ -50,7 +50,7 @@ template <class T>
|
||||
struct Template_Unused {};
|
||||
|
||||
template <class T>
|
||||
struct MOZ_NON_MEMMOVABLE Template_NonMovable {}; // expected-note-re + {{'{{.*}}' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'Template_NonMovable<{{.*}}>'}}
|
||||
struct MOZ_NON_MEMMOVABLE Template_NonMovable {};
|
||||
|
||||
/*
|
||||
These tests take the following form:
|
||||
@ -499,7 +499,7 @@ struct W_NeedyTemplate6 {
|
||||
template <class T>
|
||||
struct SW_NeedyTemplate6 : W_NeedyTemplate6<T> {};
|
||||
// We create a different NonMovable type here, as NeedyTemplate6 will already be instantiated with NonMovable
|
||||
struct MOZ_NON_MEMMOVABLE NonMovable2 {}; // expected-note {{'NonMovable2' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'NonMovable2'}}
|
||||
struct MOZ_NON_MEMMOVABLE NonMovable2 {};
|
||||
template <class T = NonMovable2>
|
||||
struct Defaulted_SW_NeedyTemplate6 {
|
||||
SW_NeedyTemplate6<T> m;
|
||||
@ -748,8 +748,8 @@ void good8() {
|
||||
instantiate NeedyTemplate.
|
||||
*/
|
||||
|
||||
struct MOZ_NON_MEMMOVABLE SpecializedNonMovable {}; // expected-note 8 {{'S_SpecializedNonMovable' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'SpecializedNonMovable'}} expected-note 8 {{'Template_Inline<SpecializedNonMovable>' is non-memmovable because of the MOZ_NON_MEMMOVABLE annotation on 'SpecializedNonMovable'}}
|
||||
struct S_SpecializedNonMovable : SpecializedNonMovable {};
|
||||
struct MOZ_NON_MEMMOVABLE SpecializedNonMovable {};
|
||||
struct S_SpecializedNonMovable : SpecializedNonMovable {}; // expected-note 8 {{'S_SpecializedNonMovable' is a non-memmove()able type because it inherits from a non-memmove()able type 'SpecializedNonMovable'}}
|
||||
|
||||
// Specialize all of the NeedyTemplates with SpecializedNonMovable.
|
||||
template <>
|
||||
|
Loading…
Reference in New Issue
Block a user