source: src/Validate/HandleAttributes.cc @ 05e6eb5

aaron-thesisarm-ehcleanup-dtorsdeferred_resndemanglerjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprno_listpersistent-indexer
Last change on this file since 05e6eb5 was 05e6eb5, checked in by Rob Schluntz <rschlunt@…>, 3 years ago

Warn about constructor/destructor priorities 101-200 only when not building the library

  • Property mode set to 100644
File size: 5.0 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2018 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// HandleAttributes.cc --
8//
9// Author           : Rob Schluntz
10// Created On       : Fri Jul 27 10:15:06 2018
11// Last Modified By : Rob Schluntz
12// Last Modified On : Fri Jul 27 10:16:43 2018
13// Update Count     : 2
14//
15
16#include "HandleAttributes.h"
17
18#include <utility> // for pair
19
20#include "CompilationState.h"
21#include "Common/PassVisitor.h"
22#include "Common/SemanticError.h"
23#include "InitTweak/InitTweak.h"
24#include "ResolvExpr/Resolver.h"
25#include "SynTree/Attribute.h"
26#include "SynTree/Declaration.h"
27#include "SynTree/Type.h"
28
29namespace Validate {
30        namespace {
31                std::pair<long long int, bool> eval(Expression * expr);
32
33                struct Eval : public WithShortCircuiting {
34                        long long int value = 0;
35                        bool valid = true;
36
37                        void previsit( BaseSyntaxNode * ) { visit_children = false; }
38                        void postvisit( BaseSyntaxNode * ) { valid = false; }
39
40                        void postvisit( ConstantExpr * expr ) {
41                                value = expr->intValue();
42                        }
43
44                        void postvisit( CastExpr * expr ) {
45                                auto arg = eval(expr->arg);
46                                valid = arg.second;
47                                value = arg.first;
48                                // TODO: perform type conversion on value if valid
49                        }
50
51                        void postvisit( VariableExpr * expr ) {
52                                if ( EnumInstType * inst = dynamic_cast<EnumInstType *>(expr->result) ) {
53                                        if ( EnumDecl * decl = inst->baseEnum ) {
54                                                if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
55                                                        return;
56                                                }
57                                        }
58                                }
59                                valid = false;
60                        }
61
62                        void postvisit( ApplicationExpr * expr ) {
63                                DeclarationWithType * function = InitTweak::getFunction(expr);
64                                if ( ! function || function->linkage != LinkageSpec::Intrinsic ) { valid = false; return; }
65                                const std::string & fname = function->name;
66                                assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
67                                std::pair<long long int, bool> arg1, arg2;
68                                arg1 = eval(expr->args.front());
69                                valid = valid && arg1.second;
70                                if ( ! valid ) return;
71                                if ( expr->args.size() == 2 ) {
72                                        arg2 = eval(expr->args.back());
73                                        valid = valid && arg2.second;
74                                        if ( ! valid ) return;
75                                }
76                                if (fname == "?+?") {
77                                        value = arg1.first + arg2.first;
78                                } else if (fname == "?-?") {
79                                        value = arg1.first - arg2.first;
80                                } else if (fname == "?*?") {
81                                        value = arg1.first * arg2.first;
82                                } else if (fname == "?/?") {
83                                        value = arg1.first / arg2.first;
84                                } else if (fname == "?%?") {
85                                        value = arg1.first % arg2.first;
86                                } else {
87                                        valid = false;
88                                }
89                                // TODO: implement other intrinsic functions
90                        }
91                };
92
93                std::pair<long long int, bool> eval(Expression * expr) {
94                        PassVisitor<Eval> ev;
95                        if (expr) {
96                                expr->accept(ev);
97                                return std::make_pair(ev.pass.value, ev.pass.valid);
98                        } else {
99                                return std::make_pair(0, false);
100                        }
101                }
102
103                struct HandleAttributes : public WithIndexer {
104                        void previsit( ObjectDecl * decl );
105                        void previsit( FunctionDecl * decl );
106                };
107        } // namespace
108
109        void handleAttributes( std::list< Declaration * > &translationUnit ) {
110                PassVisitor<HandleAttributes> handler;
111                acceptAll( translationUnit, handler );
112        }
113
114        namespace {
115                void HandleAttributes::previsit( ObjectDecl * decl ) {
116                        for ( Attribute * attr : decl->attributes ) {
117                                std::string name = attr->normalizedName();
118                                if (name == "init_priority") {
119                                        // TODO: implement C++-like init_priority attribute
120                                }
121                        }
122                }
123
124                void HandleAttributes::previsit( FunctionDecl * decl ) {
125                        for ( Attribute * attr : decl->attributes ) {
126                                std::string name = attr->normalizedName();
127                                if (name == "constructor" || name == "destructor") {
128                                        if (attr->parameters.size() == 1) {
129                                                Expression *& arg = attr->parameters.front();
130                                                ResolvExpr::findSingleExpression( arg, new BasicType( Type::Qualifiers(), BasicType::LongLongSignedInt ), indexer );
131                                                auto result = eval(arg);
132                                                if (! result.second) {
133                                                        SemanticWarning(attr->location, Warning::GccAttributes,
134                                                                toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
135                                                        return;
136                                                }
137                                                auto priority = result.first;
138                                                if (priority < 101) {
139                                                        SemanticWarning(attr->location, Warning::GccAttributes,
140                                                                toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
141                                                } else if (priority < 201 && ! buildingLibrary()) {
142                                                        SemanticWarning(attr->location, Warning::GccAttributes,
143                                                                toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
144                                                }
145                                        } else if (attr->parameters.size() > 1) {
146                                                SemanticWarning(attr->location, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
147                                        } else {
148                                                SemanticWarning(attr->location, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
149                                        }
150                                }
151                        }
152                }
153        } // namespace
154} // namespace Validate
155
156// Local Variables: //
157// tab-width: 4 //
158// mode: c++ //
159// compile-command: "make install" //
160// End: //
Note: See TracBrowser for help on using the repository browser.