CGF.Builder.ClearInsertionPoint();
}
+static bool hasObjCExceptionAttribute(const ObjCInterfaceDecl *OID) {
+ if (OID->getAttr<ObjCExceptionAttr>())
+ return true;
+ if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
+ return hasObjCExceptionAttribute(Super);
+ return false;
+}
+
llvm::Value *
CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceType *IT) {
const ObjCInterfaceDecl *ID = IT->getDecl();
if (Entry)
return Entry;
+ // If this type (or a super class) has the __objc_exception__
+ // attribute, emit an external reference.
+ if (hasObjCExceptionAttribute(IT->getDecl()))
+ return Entry =
+ new llvm::GlobalVariable(ObjCTypes.EHTypeTy, false,
+ llvm::GlobalValue::ExternalLinkage,
+ 0,
+ (std::string("OBJC_EHTYPE_$_") +
+ ID->getIdentifier()->getName()),
+ &CGM.getModule());
+
std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
std::string VTableName = "objc_ehtype_vtable";
llvm::GlobalVariable *VTableGV =
// RUN: grep '@"OBJC_METACLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t &&
// RUN: grep '@"OBJC_CLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH" = weak global .*section "__DATA,__datacoal_nt,coalesced"' %t &&
+// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak global .*section "__DATA,__datacoal_nt,coalesced"' %t &&
+// RUN: grep '@"OBJC_EHTYPE_$_EH2" = external global' %t &&
// RUN: grep -F 'define internal void @"\01-[A im0]"' %t &&
// FIXME: Should include category name.
// RUN: grep -F 'define internal void @"\01-[A im1]"' %t &&
// RUN: grep '@"OBJC_METACLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t &&
// FIXME: This is wrong, should be hidden
// RUN: grep '@"OBJC_CLASS_$_A" = global .*section "__DATA, __objc_data", align 8' %t &&
-// RUN: grep '@"OBJC_EHTYPE_$_EH" = weak hidden global .*section "__DATA,__datacoal_nt,coalesced"' %t &&
+// RUN: grep '@"OBJC_EHTYPE_$_EH1" = weak hidden global .*section "__DATA,__datacoal_nt,coalesced"' %t &&
// RUN: grep -F 'define internal void @"\01-[A im0]"' %t &&
// FIXME: Should include category name.
// RUN: grep -F 'define internal void @"\01-[A im1]"' %t &&
}
@end
-@interface EH
+@interface EH1
+@end
+
+__attribute__((__objc_exception__))
+@interface EH2
@end
void f1();
void f0(id x) {
@try {
f1();
- } @catch (EH *x) {
+ } @catch (EH1 *x) {
+ } @catch (EH2 *x) {
}
}
def __len__(self):
return len(self.data)
-kGCCErrorRE = re.compile('(.*):([0-9]+): error: (.*)')
-kGCCWarningRE = re.compile('(.*):([0-9]+): warning: (.*)')
-kClangErrorRE = re.compile('(.*):([0-9]+):([0-9]+): error: (.*)')
-kClangWarningRE = re.compile('(.*):([0-9]+):([0-9]+): warning: (.*)')
+kDiagnosticRE = re.compile(': (error|warning): (.*)')
kAssertionRE = re.compile('Assertion failed: (.*, function .*, file .*, line [0-9]+\\.)')
-kStackDumpLineRE = re.compile('^[0-9]+ +([^ ]+) +0x[0-9a-fA-F]+ +([^ ]+)')
def readInfo(path, opts):
+ lastProgress = [-100,0]
+ def progress(pos):
+ pct = (100. * pos) / (size * 2)
+ if (pct - lastProgress[0]) >= 10:
+ lastProgress[0] = pct
+ print '%d/%d = %.2f%%' % (pos, size*2, pct)
+
f = open(path)
data = f.read()
f.close()
if opts.truncate != -1:
data = data[:opts.truncate]
- gccwarnings = multidict([(m.group(3),m) for m in kGCCWarningRE.finditer(data)]).items()
- gccerrors = multidict([(m.group(3),m) for m in kGCCErrorRE.finditer(data)]).items()
- assertions = multidict([(m.group(1),m) for m in kAssertionRE.finditer(data)]).items()
+ size = len(data)
+ warnings = multidict()
+ errors = multidict()
+ for m in kDiagnosticRE.finditer(data):
+ progress(m.end())
+ if m.group(1) == 'error':
+ d = errors
+ else:
+ d = warnings
+ d[m.group(2)] = m
+ warnings = warnings.items()
+ errors = errors.items()
+ assertions = multidict()
+ for m in kAssertionRE.finditer(data):
+ print '%d/%d = %.2f%%' % (size + m.end(), size, (float(m.end()) / (size*2)) * 100.)
+ assertions[m.group(1)] = m
+ assertions = assertions.items()
# Manual scan for stack traces
aborts = multidict()
- prevLine = None
- lnIter = iter(data.split('\n'))
- for ln in lnIter:
- m = kStackDumpLineRE.match(ln)
- if m:
- stack = [m.group(2)]
- for ln in lnIter:
- m = kStackDumpLineRE.match(ln)
- if not m:
- break
- stack.append(m.group(2))
- if prevLine is None or not kAssertionRE.match(prevLine):
- aborts[tuple(stack)] = stack
- prevLine = ln
+ if 0:
+ prevLine = None
+ lnIter = iter(data.split('\n'))
+ for ln in lnIter:
+ m = kStackDumpLineRE.match(ln)
+ if m:
+ stack = [m.group(2)]
+ for ln in lnIter:
+ m = kStackDumpLineRE.match(ln)
+ if not m:
+ break
+ stack.append(m.group(2))
+ if prevLine is None or not kAssertionRE.match(prevLine):
+ aborts[tuple(stack)] = stack
+ prevLine = ln
sections = [
- (gccwarnings, 'Warnings'),
- (gccerrors, 'Errors'),
+ (warnings, 'Warnings'),
+ (errors, 'Errors'),
(assertions, 'Assertions'),
(aborts.items(), 'Aborts'),
]