1616
1717import cpp
1818import codingstandards.cpp.misra
19- import codingstandards.cpp.util.CondensedList
20- import codingstandards.cpp.util.Pair
19+ import qtil.Qtil
2120
2221class DefOrUndef extends PreprocessorDirective {
23- string name ;
22+ DefOrUndef ( ) { this instanceof PreprocessorUndef or this instanceof Macro }
2423
25- DefOrUndef ( ) {
26- name = this .( PreprocessorUndef ) .getName ( ) or
27- name = this .( Macro ) .getName ( )
24+ string getName ( ) {
25+ result = this .( PreprocessorUndef ) .getName ( ) or
26+ result = this .( Macro ) .getName ( )
2827}
29-
30- string getName ( ) { result = name }
3128}
3229
3330predicate relevantNameAndFile ( string name , File file ) {
@@ -37,30 +34,24 @@ predicate relevantNameAndFile(string name, File file) {
3734)
3835}
3936
40- class StringFilePair = Pair< string , File > :: Where< relevantNameAndFile / 2 > :: Pair ;
41-
42- module DefUndefListConfigimplements CondensedListSig {
43- class Division = StringFilePair ;
37+ class StringFilePair = Qtil:: Pair< string , File , relevantNameAndFile / 2 > :: Pair ;
4438
45- class Item = DefOrUndef ;
39+ /**
40+ * Defs and undefs ordered by location, grouped by name and file.
41+ */
42+ class OrderedDefOrUndef extends Qtil:: Ordered< DefOrUndef > :: GroupBy< StringFilePair > :: Type {
43+ override int getOrder ( ) { result = getLocation ( ) .getStartLine ( ) }
4644
47- int getSparseIndex ( StringFilePair division , DefOrUndef directive ) {
48- directive .getName ( ) = division .getFirst ( ) and
49- directive .getFile ( ) = division .getSecond ( ) and
50- result = directive .getLocation ( ) .getStartLine ( )
45+ override StringFilePair getGroup ( ) {
46+ result .getFirst ( ) = getName ( ) and result .getSecond ( ) = getFile ( )
5147}
5248}
5349
54- class ListEntry = Condense< DefUndefListConfig > :: ListEntry ;
55-
56- from PreprocessorUndef undef , ListEntry defUndefListEntry
50+ from OrderedDefOrUndef defOrUndef
5751where
58- not isExcluded ( undef , PreprocessorPackage:: undefOfMacroNotDefinedInFileQuery ( ) ) and
59- // There exists a def or undef for a given name and file, and it is an #undef
60- undef = defUndefListEntry .getItem ( ) and
61- // Exclude cases where the previous def or undef with the same name in the same file is a #define
62- not exists ( ListEntry prev |
63- prev = defUndefListEntry .getPrev ( ) and
64- prev .getItem ( ) instanceof Macro
65- )
66- select undef , "Undef of name '" + undef .getName ( ) + "' not defined in the same file."
52+ not isExcluded ( defOrUndef , PreprocessorPackage:: undefOfMacroNotDefinedInFileQuery ( ) ) and
53+ // There exists an #undef for a given name and file
54+ defOrUndef instanceof PreprocessorUndef and
55+ // A previous def or undef of this name must exist in this file, and it must be a #define
56+ not defOrUndef .getPrevious ( ) instanceof Macro
57+ select defOrUndef , "Undef of name '" + defOrUndef .getName ( ) + "' not defined in the same file."